我有一个列表,它包含一个特定数字'5.74536541'
,我将其转换为浮点数。
我使用("%0.2f" % (variable))
在Python 3中打印出来但它总是输出5.75而不是5.74。
我知道你在考虑谁在乎,但这是货币转换器计划,我不希望货币向上/向下舍入,但确切地说。
如何保持它不被舍入而且还保留2位小数?
答案 0 :(得分:9)
由于您提到的舍入错误,您不应该使用浮点数作为货币。
您最好的选择是使用fixed-precision decimal
,您也可以完全控制舍入和截断的工作方式。来自文档:
>>> from decimal import *
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999,
capitals=1, flags=[], traps=[Overflow, DivisionByZero,
InvalidOperation])
>>> getcontext().prec = 6
>>> Decimal('3.0')
Decimal('3.0')
>>> Decimal('3.1415926535')
Decimal('3.1415926535')
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85987')
>>> getcontext().rounding = ROUND_UP
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85988')
您应该在内部将所有基于货币的值表示为Decimals
,并且具有高精度(在您的情况下,标准精度水平应该没问题 - 只需单独留下prec
!)。如果要向用户打印格式良好的美元和美分值,使用locale
模块是一种直接的方法。
打印时要小心,因为您必须将Decimal
量化为正确的显示位数,否则舍入将不会基于您的Decimal
上下文!您应该只执行最后显示的quantize
步骤或单个最终值 - 所有中间步骤都应使用高精度Decimal
来使任何操作尽可能准确。
>>> from decimal import *
>>> import locale
>>> locale.setlocale(locale.LC_ALL, '')
'en_AU.UTF-8'
>>> getcontext().rounding = ROUND_DOWN
>>> TWOPLACES = Decimal(10) ** -2
>>> var = Decimal('5.74536541')
Decimal('5.74536541')
>>> var.quantize(TWOPLACES)
Decimal('5.74')
>>> locale.currency(var.quantize(TWOPLACES))
'$5.74'
答案 1 :(得分:4)
如果您处理货币和准确性问题,请不要使用float
,请使用decimal
。
答案 2 :(得分:1)
浮点值称为“有用的近似值”。无论你对浮点数做什么 - 舍入它,截断它,无论如何 - 如果结果是浮点值,你不能决定小数点右边有多少位数它有。
从不使用货币的浮点值。例如,请参阅pydoc decimal
。 Python的十进制模块支持十进制定点和十进制浮点运算。
Python docs warn about rounding floats。
注意浮点数的round()行为可能会令人惊讶:for 例如,round(2.675,2)给出2.67而不是预期的2.68。这个 这不是一个错误:它是大多数小数部分的结果 不能完全表示为浮点数。
如果你不小心,你将成为misled by the value that appears at the interpreter prompt。
Python仅打印十进制逼近真实的十进制值 机器存储的二进制近似值。
和
重要的是要意识到这是一种真正意义上的错觉: 机器中的值不完全是1/10,你只是四舍五入 显示真机价值。这个事实很明显 一旦你尝试用这些值算术
答案 3 :(得分:1)
取走数量mod 0.01
即
rounded = number - (number % 0.01)
然后像以前一样打印它。
这就是说,四舍五入是不更准确。你是否试图通过利用舍入误差计划从银行偷钱?
答案 4 :(得分:-2)
如果数字是字符串,则将字符串截断为小数点后仅2个字符,然后将其转换为float。 否则将其乘以10 ^ n,其中n是小数点后的位数,然后将浮点数除以10 ^ n。