tkb*_*kbx 62 python math rounding
有没有办法将python float舍入到x小数?例如:
>>> x = roundfloat(66.66666666666, 4)
66.6667
>>>x = roundfloat(1.29578293, 6)
1.295783
Run Code Online (Sandbox Code Playgroud)
我已经找到了修剪/截断它们的方法(66.666666666 - > 66.6666),但不是圆形(66.666666666 - > 66.6667).
Mar*_*son 117
我觉得有必要对Ashwini Chaudhary的回答提出一个对立面.尽管有外观,但round函数的双参数形式并没有将Python浮点数舍入到给定的小数位数,并且它通常不是您想要的解决方案,即使您认为它也是如此.让我解释...
将(Python)浮点数舍入到一定数量的小数位的能力是经常要求的,但事实证明很少是实际需要的.简单的回答round(x, number_of_places)是一个有吸引力的麻烦:看起来它就像你想要的那样,但是由于Python浮动内部以二进制形式存储,它正在做一些相当微妙的事情.请考虑以下示例:
>>> round(52.15, 1)
52.1
Run Code Online (Sandbox Code Playgroud)
随着一个什么样的幼稚理解round呢,这看起来错了:当然应该四舍五入达至52.2,而不是下降到52.1?要理解为什么不能依赖这些行为,你需要意识到虽然这看起来像一个简单的十进制到十进制操作,但它远非简单.
所以这就是上面例子中真正发生的事情.(深吸一口气)我们显示小数最近的表示二进制浮点数到最近n-digits-后的点十进制数的二进制数字文字写成的浮点近似小数.因此,为了从原始数字文字到显示的输出,底层机制在二进制和十进制格式之间进行了四次单独的转换,每个方向两次.打破它(和通常的免责声明关于假设IEEE 754 binary64格式,round-ties-to-even rounding和IEEE 754规则):
首先,数字文字52.15被解析并转换为Python float.存储的实际数字是7339460017730355 * 2**-47,或52.14999999999999857891452847979962825775146484375.
在内部作为round操作的第一步,Python计算最接近的1位数后点十进制字符串到存储的数字.由于存储的数字是原始值下的触摸52.15,我们最终向下舍入并获得一个字符串52.1.这就解释了为什么我们将其52.1作为最终输出而不是52.2.
然后在round操作的第二步中,Python将该字符串转换回浮点数,获得最接近的二进制浮点数52.1,现在7332423143312589 * 2**-47或者52.10000000000000142108547152020037174224853515625.
最后,作为Python的read-eval-print循环(REPL)的一部分,将显示浮点值(十进制).这涉及将二进制值转换回十进制字符串,52.1作为最终输出.
在Python 2.7及更高版本中,我们遇到了令人愉快的情况,即步骤3和4中的两次转换相互抵消.这是由于Python的repr实现选择,它产生最短的十进制值,保证正确地舍入到实际浮点数.这种选择的一个结果是,如果你从15位或更少有效数字的任何(不是太大,不是太小)十进制文字开始,那么将显示相应的浮点数,显示那些完全相同的数字:
>>> x = 15.34509809234
>>> x
15.34509809234
Run Code Online (Sandbox Code Playgroud)
不幸的是,这进一步加剧了Python以十进制存储值的错觉.但在Python 2.6中却不是这样!这是在Python 2.6中执行的原始示例:
>>> round(52.15, 1)
52.200000000000003
Run Code Online (Sandbox Code Playgroud)
我们不仅在相反的方向上转,52.2而是取而代之52.1,但显示的值甚至不打印为52.2!这种行为导致了许多关于"bug is broken!"的Python bug跟踪器的报告.但它并没有round被打破,这是用户的期望.(好吧,好吧,round是一个小位在Python 2.6打破,因为它不使用正确的舍入.)
简短版本:如果你正在使用双参数回合,并且你期望从二进制近似到二进制近似到十进制中间情况的十进制轮次的可预测行为,那么你就会遇到麻烦.
因此,"两个参数回合是不好的"论点就足够了.你应该用什么呢?根据您的尝试,有几种可能性.
如果你为了显示目的而四舍五入,那么你根本不需要浮动结果; 你想要一个字符串.在这种情况下,答案是使用字符串格式:
>>> format(66.66666666666, '.4f')
'66.6667'
>>> format(1.29578293, '.6f')
'1.295783'
Run Code Online (Sandbox Code Playgroud)
即使这样,人们也必须意识到内部二进制表示,以免被明显的十进制中间情况的行为感到惊讶.
>>> format(52.15, '.1f')
'52.1'
Run Code Online (Sandbox Code Playgroud)如果您在一个重要的上下文中操作十进制中间情况的方向(例如,在某些财务上下文中),您可能希望使用该Decimal类型表示您的数字.对Decimal类型进行十进制舍入比使用二进制类型更有意义(同样地,舍入到固定数量的二进制位置对于二进制类型是完全有意义的).此外,该decimal模块可以更好地控制舍入模式.在Python 3中,round直接完成工作.在Python 2中,您需要该quantize方法.
>>> Decimal('66.66666666666').quantize(Decimal('1e-4'))
Decimal('66.6667')
>>> Decimal('1.29578293').quantize(Decimal('1e-6'))
Decimal('1.295783')
Run Code Online (Sandbox Code Playgroud)在极少数情况下,两个版本的版本round确实是你想要的:也许你正在将浮动装箱分成大小的箱子0.01,而你并不特别关心边境案件的走向.然而,这些案例很少见,并且很难证明round单独根据这些案例存在内置的双参数版本.
Ash*_*ary 68
使用内置功能round():
In [23]: round(66.66666666666,4)
Out[23]: 66.6667
In [24]: round(1.29578293,6)
Out[24]: 1.295783
Run Code Online (Sandbox Code Playgroud)
帮助round():
round(number [,ndigits]) - >浮点数
将数字舍入到给定精度的十进制数字(默认为0位).这总是返回一个浮点数.精度可能是负面的.