Python плавающее число [дубликат]

10
задан fmark 6 June 2010 в 23:08
поделиться

3 ответа

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

Очень важно знать об этом, потому что это приводит к некоторым странным побочным эффектам. Например, вы можете очень разумно подумать, что сумма десяти лотов 0,1 будет 1,0 . Хотя это кажется логичным, это также неверно, когда дело касается чисел с плавающей запятой:

>>> f = 0.0
>>> for _ in range (10):
...  f += 0.1
...
>>> print f == 1.0
False
>>> f
0.99999999999999989
>>> str(f)
1.0

Вы можете подумать, что n / m * m == n . И снова мир с плавающей запятой не согласен:

>>> (1.0 / 103.0) * 103.0
0.99999999999999989

Или, возможно, так же странно, можно было бы подумать, что для всех n , n + 1! = N . В мире чисел с плавающей запятой числа просто не работают следующим образом:

>>> 10.0**200
9.9999999999999997e+199
>>> 10.0**200 == 10.0**200 + 1
True
# How much do we have to add to 10.0**200 before its 
# floating point representation changes?
>>> 10.0**200 == 10.0**200 + 10.0**183
True
>>> 10.0**200 == 10.0**200 + 10.0**184
False

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

Если вам нужно точное десятичное представление, ознакомьтесь с модулем decimal , который входит в стандартную библиотеку Python начиная с версии 2.4. Он позволяет указать количество значащих цифр. Обратной стороной является то, что он намного медленнее, чем с плавающей запятой, потому что операции с плавающей запятой реализованы аппаратно, тогда как десятичные операции выполняются чисто программно. У него также есть свои проблемы с неточностью, но если вам нужно точное представление десятичных чисел (например, для финансового приложения), это идеальный вариант.

Например:

>>> 3.14
3.1400000000000001
>>> import decimal
>>> decimal.Decimal('3.14')
>>> print decimal.Decimal('3.14')
3.14
# change the precision:
>>> decimal.getcontext().prec = 6
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.142857')
>>> decimal.getcontext().prec = 28
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1428571428571428571428571429')
14
ответ дан 3 December 2019 в 20:03
поделиться

Как упоминалось ранее, все дело в приближении с плавающей запятой.

Если вам нужна точность, вы можете использовать десятичную дробь (которая является точным представлением): http://docs.python.org/library/decimal.html

a = [1.5, 1.49999]
a
[1.5, 1.4999899999999999]

from decimal import Decimal
b = [1.5, Decimal('1.4999')]
b
[1.5, Decimal('1.4999')]
0
ответ дан 3 December 2019 в 20:03
поделиться

Стоит отметить, что в Python 3.1 есть новая процедура вывода с плавающей точкой, которая округляет это ожидаемым образом (она также была перенесена в Python 2.7):

Python 3.1 (r31:73572, Aug 15 2009, 17:12:41) 
[GCC 4.0.1 (Apple Computer, Inc. build 5367)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = [3.14]
>>> print(a)
[3.14]

Из документа Что нового в Python 3.1:

Python теперь использует алгоритм Дэвида Гея для нахождения кратчайшего представления с плавающей точкой, которое не меняет своего значения. Это должно помочь уменьшить некоторую путаницу, связанную с двоичными числами с плавающей запятой.

Значение легко увидеть на примере такого числа, как 1.1, которое не имеет точного эквивалента в двоичной системе с плавающей запятой. Поскольку точного эквивалента нет, выражение типа float('1.1') оценивается в ближайшее представимое значение, которое равно 0x1.199999999999ap+0 в шестнадцатеричной системе счисления или 1.100000000000000088817841970012523233890533447265625 в десятичной. Это ближайшее значение использовалось и до сих пор используется в последующих вычислениях с плавающей запятой.

6
ответ дан 3 December 2019 в 20:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: