Все мы знаем, что использование чисел с плавающей запятой может привести к странным результатам:
>>> 0.1*3
0.30000000000000004
Мой вопрос: можно ли считать все числа с плавающей запятой, заканчивающиеся на .0
, математическими целыми числами?
Мой вариант использования:
>>> x = 3.4296875
>>> 2*x*(128*x-695)+1856
100.0
Можно ли утверждать, что никакой причуды нет и что результат — истинная и точная 100? Я имею в виду, не делая расчет вручную!
Спасибо!
Краткий ответ нет
@aka.nice: Короткий ответ: да. 3,4296875 равно 439/128, и все промежуточные вычисления дают точные результаты. Конечным результатом является математическое целое число.
Арифметика с плавающей запятой — это не причудливый магический беспорядок. Это точная арифметика (ведь ею занимается машина, а не пьяный лепрекон). Это просто намного сложнее или, вернее, гораздо более неизвестно, чем натуральные числа или арифметика действительных чисел. Так коротко или долго, ответ - нет. Даже Python, который иногда (слишком) круто выглядит в отношении типов, знает об этом:
>>> x = 1+1e-100
>>> x == 1
True
>>> isinstance(x,int)
False
>>> isinstance(x,float)
True
Работа Уильяма Кахана была достаточно педагогической, чтобы заставить нас осознать все опасности заманчивых коротких путей.
isinstance(x,int)
проверяет, является ли тип x
типом int
, а не является ли значение x
целым математическим числом.
Есть несколько возможных интерпретаций этого вопроса или вариантов вопросов, которые могут быть заданы, поэтому я перечислил некоторые из них и рассмотрел их по отдельности.
да. В соответствии со стандартом IEEE-754 для операций с плавающей запятой и, как правило, с другими форматами с плавающей запятой объект с плавающей запятой представляет собой одно конкретное число (или бесконечность, или NaN). Он не представляет интервал чисел. Таким образом, если объект с плавающей запятой не является NaN или бесконечностью, а его дробная часть равна нулю, то значение, которое он представляет, является целым числом.
Когда пишутся доказательства арифметики с плавающей запятой, тот факт, что различные значения являются целыми числами, обычно используется как часть доказательства.
Не в целом. Из-за ограниченной точности и округления вычисления с плавающей запятой и вычисления с действительными числами могут различаться на произвольные величины.
В определенных случаях можно проанализировать операции с плавающей запятой и получить утверждения о том, что результаты с плавающей запятой подразумевают относительно результатов с действительными числами.
Не обязательно. Когда числа с плавающей запятой форматируются для отображения, они обычно округляются до ограниченного числа десятичных цифр. Это может скрыть точное значение, а некоторые числа с ненулевыми частями могут отображаться с «.0».
Это зависит от используемого языка программирования. В строго типизированных языках нет, значение остается типом с плавающей запятой. В языках сценариев довольно часто используется некоторая гибкость в использовании результатов с плавающей запятой как целых чисел.
В коде, показанном в вопросе, нет ошибок округления. Значение для x
, 3,4296875, точно равно 439/128, и это можно представить без ошибок во всех распространенных форматах с плавающей запятой. Таким образом, умножение его на 128 дает точный результат, 439. Вычитание 695 из этого дает -256, а умножение 2*x*-256
дает точно -1756, а затем добавление 1856 дает ровно 100. Это целое число. Это может быть неверно в других случаях, когда используются нецелочисленные данные.
Что вы подразумеваете под «результатом является точное целое число»? Что вычисление, выполняемое компьютером, является целым числом? Или что математический результат является целым числом? 1.0+10^-100!=1 и математически не является целым числом, а результат (из-за округления) является является целым числом.