Тип float в python представляет только приближения к действительным числам? - PullRequest
0 голосов
/ 26 августа 2018

Я новичок в программировании и изучаю основные сейчас. Мне интересно, что тип float в Python представляет только приближения к реальному числу? Я знаю, что float использует двоичные дроби, но являются ли значения с плавающей запятой 0,5, 0,25, 0,125 и т. Д. Еще приблизительными? Я попробовал:

sum([0.1] * 10) == 1

вернул Ложь.

Но

sum([0.5] * 10) == 5

Вернул Истину.

Наконец я попробовал:

for i in range(1, 8):
    answer = sum([1 / 2 ** i] * 10)
    print(answer == 1 / 2 ** i * 10)

Ответ - все верно.

Это значит, что некоторые числа с плавающей точкой в ​​Python - это именно действительные числа, а не приближения?

Ответы [ 2 ]

0 голосов
/ 26 августа 2018

Python представляет числа с плавающей запятой в виде двоичных дробей.Следовательно, числа типа 0.5 могут быть представлены точно, а 0.1, например, не может.Числа с плавающей точкой в ​​Python являются лишь приблизительными, если они не могут быть точно представлены с использованием двоичных дробей.Если вам нужна большая точность при работе с арифметикой с плавающей запятой, я бы посоветовал взглянуть на десятичные дроби: https://docs.python.org/3/library/decimal.html

Кроме того, хороший ресурс по числам с плавающей запятой в Python можно найти здесь: https://docs.python.org/3/tutorial/floatingpoint.html

0 голосов
/ 26 августа 2018

Каждый объект с плавающей запятой точно представляет одно число (или специальное значение, например, NaN). Объекты с плавающей точкой не представляют приближения.

Правильный способ думать о числах с плавающей точкой состоит в том, что значения с плавающей точкой являются точными числами, но операции с плавающей точкой приближаются к реальной арифметике.

Python точно не определяет арифметику с плавающей точкой; каждая реализация Python может использовать базовую арифметику платформы, на которой она реализована. Обычно используются форматы IEEE 754, хотя операции могут не полностью соответствовать IEEE 754. Чтобы проиллюстрировать, что происходит с вашим кодом, я буду использовать базовый 64-разрядный двоичный код с плавающей точкой IEEE-754.

При обработке исходного текста 0.5 он преобразуется в число с плавающей запятой. Обратите внимание, что преобразование является операцией, так же как сложение или умножение являются операциями. Символы интерпретируются как десятичное число, и преобразование создает число с плавающей запятой, которое является ближайшим к числу, представленному десятичным числом. В этом случае 0.5 представляет половину, и это точно представлено в двоичной форме с плавающей запятой, поэтому результат равен точно 0,5.

Затем [0.5] * 10 создает список, содержащий десять копий по 0,5, а sum добавляет их. Все сложения, выполненные в этом суммировании, являются точными, поскольку формат с плавающей точкой может точно представлять 0,5, 1, 1,5, 2 и т. Д. Таким образом, результат равен именно 5, и сравнение с 5 дает истину.

С другой стороны, при обработке исходного текста 0.1 эта десятичная цифра представляет одну десятую, что не может быть точно представлено. В результате преобразования получается ближайшее представимое значение, равное 0,1000000000000000055511151231257827021181583404541015625.

Когда sum добавляет десять копий, сложение не всегда может быть выполнено точно. Точное добавление первых двух, добавление 0.1000000000000000055511151231257827021181583404541015625 к 0.1000000000000000055511151231257827021181583404541015625 приводит к 0.200000000000000011102230246251565404236316680. Однако при добавлении 0.200000000000000011102230246251565404236316680908203125 к 0.1000000000000000055511151231257827021181583404541015625, результат составляет 0,3000000000000000444089209850062616169125667236. Во время этого добавления биты в добавлении переносятся в новую позицию (операнды находятся под ¼, но результат больше ¼ - сложение переносится в позицию Since. Поскольку формат с плавающей запятой имеет только фиксированное число битов ( 53) доступное для значения, операция должна была отбрасывать младший бит. При этом он немного изменил результат. Так что это сложение только приблизительное.

Поскольку эти добавления продолжаются, окончательное значение составляет 0,999999999999999988897769753748434595763683319091796875. Если сравнить с 1, результат будет ложным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...