{{notification.text}}

MirGames

Хотел написать простенькую утилитку для решения лабы на руби. В общем, так родился следующий диалог с irb:
irb(main):001:0> a = 1 — 0.8
=> 0.19999999999999996
irb(main):002:0> a + 0.8
=> 1.0

Ну, ничего себе, думаю, какая какаха, окей, введу в Питоне:
>>> a = 1-0.8
>>> a
0.19999999999999996
>>> a + 0.8
1.0
:(

Посоветовали ввести в JavaScript'е (можно попробовать ввести код прямо на этой странице. ctrl + shift + F если у Вас хром + винда):
alert(1-0.8)


В общем, я шокирован.

Читаем мануал:
jack-kelly.com/concrete_example_of_floating_point_arithmetic_behaving_in

В общем, проблема на аппаратном уровне. Хех, я всегда понимал, что бывают проблемы точности. Например, понятно, что:
2/3 * 3 != 2*3 / 3

Но я никогда не ожидал, что точность может быть потеряна настолько ТУПО.

В общем, гуглю решение для рубей. Интересно, как вы решаете подобную проблему? Сильно ли она мешает жить на практике?
19.11.12 02:52

Комментарии

19.11.12 03:22

Не испытываю никаких проблем с этим. Ещё со школы приучен при сравнении вещественных чисел друг с другом использовать epsilon, и выводить с указанным уровнем точности. А в Ruby есть BigDecimal.

19.11.12 03:25

Хех, да я тож со школы привык сравнивать по eps. Просто мне всё время говорили, что это из-за делений/умножений точность теряется. Мол образуется число с бесконечной тройкой (типа 1/3 = 0.3333333...) и точность тут теряется. Но я не знал, что мы можем потерять точность на банальном сложении/вычитании.<br/>
Сразу не смог понять, как использовать BigDecimal, поэтому сейчас просто делаю что-то вроде:<br/>
<br/>
1.19999999999999999994.round(10) == 2

19.11.12 03:31

Насколько я помню, проблема была в том, что дробная часть представляется в виде суммы степеней (1/2).

19.11.12 04:08

вы ребята такие смешные. пользуетесь продвинутыми (сдерживая смех) языками не знаете о работе дробных чисел.

19.11.12 04:30

Злой ты какой-то сегодня.<br/>
Пользуемся тем, что востребовано на рынке. Это плохо?

19.11.12 15:52

да нет, я не злой просто скучно, вот и стебаюсь=)<br/>
сравнения дробных чисел (== или =) делать вообще нельзя. дробные числа после каких либо операций никогда не примут однозначное значение, причём оно может ещё и меняться в зависимости от процессора. поэтому 3 / 2 не будет = 1.5, а будет что-то типа 1.49999999999 или 1.500000000000001 и поэтому сравнение нужно всегда делать по эпсилону.

({{comment.CreationDate | date:'dd.MM.yy HH:mm'}})
Отредактировано: {{comment.UpdatedDate | date:'dd.MM.yy HH:mm'}}