Делать арифметику с двумя десятичными знаками в Python? - PullRequest
0 голосов
/ 04 мая 2010

У меня есть два числа с плавающей точкой в ​​Python, которые я хотел бы вычесть, т.е.

v1 = float(value1)
v2 = float(value2)
diff = v1 - v2

Я хочу, чтобы «diff» вычислялся с точностью до двух десятичных знаков, то есть вычислял его, используя %.2f из v1 и %.2f из v2. Как я могу это сделать? Я знаю, как печатать v1 и v2 с точностью до двух десятичных знаков, но не умею делать арифметику подобным образом.

Особая проблема, которую я пытаюсь избежать, заключается в следующем. Предположим, что:

v1 = 0.982769777778
v2 = 0.985980444444
diff = v1 - v2

и затем я печатаю в файл следующее:

myfile.write("%.2f\t%.2f\t%.2f\n" %(v1, v2, diff))

тогда я получу вывод: 0,98 0,99 0,00, предполагая, что нет разницы между v1 и v2, даже несмотря на то, что напечатанный результат предполагает разницу в 0,01. Как я могу обойти это?

спасибо.

Ответы [ 5 ]

3 голосов
/ 04 мая 2010

Вы сказали в комментарии, что не хотите использовать decimal, но, похоже, это то, что вы действительно должны использовать здесь. Обратите внимание, что это не «дополнительная библиотека», так как она поставляется по умолчанию с Python начиная с версии 2.4, вам просто нужно import decimal. Если вы хотите отобразить значения, вы можете использовать Decimal.quantize , чтобы округлить числа до 2 десятичных знаков для отображения, а затем взять разницу получаемых десятичных знаков.

>>> v1 = 0.982769777778
>>> v2 = 0.985980444444
>>> from decimal import Decimal
>>> d1 = Decimal(str(v1)).quantize(Decimal('0.01'))
>>> d2 = Decimal(str(v2)).quantize(Decimal('0.01'))
>>> diff = d2 - d1
>>> print d1, d2, diff
0.98 0.99 0.01
1 голос
/ 04 мая 2010

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

Недавно на Slashdot был хороший пост по подобным вопросам.

0 голосов
/ 04 мая 2010

Вы можете отформатировать его, используя другую строку формата. Попробуйте '%.2g' или '%.2e'. Любая приличная ссылка C / C ++ будет описывать различные спецификаторы. %.2e форматирует значение до трех значащих цифр в экспоненциальной записи - 2 означает две цифры после десятичной точки и одну цифру перед ней. %.2g приведет либо к %.2f, либо к %.2e в зависимости от того, что даст две значащие цифры в минимальном объеме пространства.

>>> v1 = 0.982769777778
>>> v2 = 0.985980444444
>>> print '%.2f' %v1
0.98
>>> print '%.2g' %v1
0.98
>>> print '%.2e' %v1
9.83e-01
>>> print '%.2g' %(v2-v1)
0.0032
>>> print '%.2e' %(v2-v1)
3.21e-03
0 голосов
/ 04 мая 2010

Что вы подразумеваете под "двумя значащими цифрами"? Python float имеет около 15 сигфигов, но он имеет ошибки представления и округления (как и decimal.Decimal.) http://docs.python.org/tutorial/floatingpoint.html может оказаться интересным для вас, наряду с большим количеством ресурсов о числа с плавающей запятой.

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

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

decimal.Decimal рекомендуется слишком много. Он может быть настроен на конкретную, более высокую, чем плавающая точность, но это очень редко требуется; Я не думаю, что когда-либо видел проблему, из-за которой кто-то должен был использовать decimal.Decimal. decimal.Decimal позволяет точно представлять десятичные числа и контролировать, как работает округление, что делает его пригодным для представления денег в некоторых контекстах.

0 голосов
/ 04 мая 2010

Особенность типа float в том, что вы не можете реально контролировать, с какой точностью выполняются вычисления . Тип float позволяет аппаратным средствам выполнять вычисления, что обычно делает их наиболее эффективными. Поскольку числа с плавающей точкой (как и большинство машинно-оптимизированных) являются двоичными, а не десятичными, непросто (или эффективно) заставить эти вычисления иметь конкретную точность в десятичном . Более подробное объяснение см. В последней главе учебника по Python . Лучшее, что вы можете сделать с помощью чисел с плавающей запятой, это округлить результат вычислений (желательно только при их форматировании).

Для управления фактическими вычислениями и точностью (в десятичной записи, не менее) вам следует рассмотреть возможность использования десятичных знаков из модуля decimal. Это дает вам гораздо больший контроль над практически всем, хотя и делает это со скоростью.

...