Широко известно, что пользователи с плавающей запятой должны следить за ошибками округления. Например, 1.0/3*3 == 1
оценивает значение false в почти каждом современном языке программирования. Более неожиданно для неспециалистов, то есть 1.0/10*10 == 1
.Плавающая точка и предотвращение ошибок округления
Однако существуют системы с плавающей запятой, которые по крайней мере кажутся более эффективными с этими проблемами. В частности, я пробовал оба вышеупомянутых теста в эмуляторах Apple II и Commodore Vic-20, и каждое выражение оценивалось как true в каждом случае. Это нелогично: очень примитивные системы работают лучше, чем более продвинутые.
Как старые системы с плавающей точкой получили желаемый ответ в вышеприведенных тестах? Предполагая, что современные плавающие точки IEEE имеют веские основания для этого, что он получает в обмен? Или иначе, в чем проблема, из-за которой старые системы с плавающей запятой были оставлены, хотя они были способны представлять 1/10 и 1/3 без самых неприятных ошибок округления?
Редактировать: Simon Byrne правильно указывает на точные тесты, которые я перечисляю выше, действительно передавайте плавающие точки IEEE. Я не знаю, какую ошибку я совершил с ними, не могу воспроизвести. Но вот один, который терпит неудачу, попробовал в Python только сейчас:
>>> 0.1+0.1+0.1 == 0.3
False
Это точный тест успешно на Apple II, так же, как же старая система получить этот результат, а то, что было компромиссом?
Невозможно ответить на историческую часть, но вы можете сохранить это число как неплавающее. Clojure имеет «дробный» класс, который хранит иррациональные числа как фракцию вместо этого, поэтому они не округлены, пока это абсолютно необходимо. – Carcigenicate
@Carcigenicate Правильно, но хранение чисел как фракций действительно нужно делать произвольной точностью, если это должно быть полезно предсказуемо, что приводит к требованию ЦП и памяти, которые исключают его в большинстве случаев, когда мы используем с плавающей запятой. – rwallace
Какой язык/платформа вы используете? '1.0/3 * 3 == 1' и' 1.0/10 * 10 == 1' должны быть истинными на любом языке/платформе с использованием IEEE754 binary64, который в наши дни довольно вездесущ. –