Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 整数转换舍入是否有不良副作用?_Python - Fatal编程技术网

Python 整数转换舍入是否有不良副作用?

Python 整数转换舍入是否有不良副作用?,python,Python,正如您所看到的,Python(和Java等)中的舍入不应该是轻率的 如果你想像你在学校学过的那样四处走动,你不应该这样做: >圆形(20.5) 20 要将“学校式”四舍五入,通常使用十进制方法: >>导入十进制数 >>>十进制。十进制(20.5)。量化(1,四舍五入=十进制。向上四舍五入) 十进制('21') 在我看来,这不是pythonic,我永远也无法记住它 另一种选择是: >>整数(20.5+0.5) 21 如果要舍入到逗号后的特定部分,请执行以下操作: >>>整数(20.5555*

正如您所看到的,Python(和Java等)中的舍入不应该是轻率的

如果你想像你在学校学过的那样四处走动,你不应该这样做:

>圆形(20.5)
20
要将“学校式”四舍五入,通常使用十进制方法:

>>导入十进制数
>>>十进制。十进制(20.5)。量化(1,四舍五入=十进制。向上四舍五入)
十进制('21')
在我看来,这不是pythonic,我永远也无法记住它

另一种选择是:

>>整数(20.5+0.5)
21
如果要舍入到逗号后的特定部分,请执行以下操作:

>>>整数(20.5555*1000+0.5)/1000
20.556
这种四舍五入的方式会产生一些不良的副作用吗?

你所描述的就是(几乎)这种策略。但是,使用
int
对负数无效:

>>> def round_half_up(x, n=0):
...     shift = 10 ** n
...     return int(x*shift + 0.5) / shift
... 
>>> round_half_up(-1.26, 1)
-1.2
相反,您应该使用
math.floor
,以便正确处理负数:

>>> import math
>>> 
>>> def round_half_up(x, n=0):
...     shift = 10 ** n
...     return math.floor(x*shift + 0.5) / shift
... 
>>> round_half_up(-1.26, 1)
-1.3
这种策略的效果是,它往往会扭曲一组数字的统计数据,例如平均值或标准差。假设您收集了一些数字,它们都以
.5
结尾;然后四舍五入将明显增加平均值:

>>> numbers = [-3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5]
>>> N = len(numbers)
>>> sum(numbers) / N
0.0
>>> sum(round_half_up(x) for x in numbers) / N
0.5
如果我们使用该策略,则会导致一些数字向上舍入,而另一些数字向下舍入,从而相互补偿:

>>> sum(round(x) for x in numbers) / N
0.0
如您所见,例如,平均值保持不变

当然,这只有在数字均匀分布的情况下才有效。如果有倾向于使用
奇数+0.5形式的数字,则此策略也不会防止出现偏差:

>>> numbers = [i + 0.5 for i in range(-3, 3, 2)]
>>> N = len(numbers)
>>> sum(numbers) / N
-0.5
>>> sum(round_half_up(x) for x in numbers) / N
0.0
>>> sum(round(x) for x in numbers) / N
0.0
对于这组数字,
round
实际上是在“对半取整”,因此两种方法都有相同的偏差

如您所见,舍入策略显然会影响一些统计数据(如平均值)的偏差。“半圆到偶数”倾向于消除这种偏见,但显然比奇数更倾向于偶数,因此也扭曲了原始分布

关于
float
对象的注释 由于浮点精度有限,这种“半舍五入”算法也可能产生一些意想不到的惊喜:

>>> round_half_up(-1.225, 2)
-1.23
-1.225
解释为十进制数,我们希望结果是
-1.22
。我们得到了
-1.23
,因为
四舍五入中的中间浮点数略高于其预期值:

>>> f'{-1.225 * 100 + 0.5:.20f}'
'-122.00000000000001421085'

floor
“数字给我们的是
-123
(而不是
-122
,如果我们以前得到
-122.0
)。这是由浮点错误引起的,首先是
-1.225
实际上并不是作为
-1.225
存储在内存中,而是作为一个稍微小一点的数字。因此,在所有情况下,使用
Decimal
是获得正确舍入的唯一方法。

我的理解是,您建议的
int(x+0.5)
应该可以很好地工作,因为它返回一个精确的整数对象。但是,您随后提出的除以1000以四舍五入到某个小数位数的建议将返回一个浮点对象,因此将遇到您正试图避免的问题。从根本上讲,除非使用十进制或纯整数完全避免浮点类型,否则无法避免浮点精度问题。

使用
decimal
是一种方法,因为不是每个浮点数都可以用
float
类型表示。如中所述,这可能导致意外行为,例如
轮(2.675,2)
给出
2.67
而不是
2.68
。这是因为可以表示
2.675
的最接近的64位
float
值实际上比这个值小一点。@a_客人:谢谢你的回答,但我想善意地告诉你,如果我想对正常的float进行四舍五入,我使用的四舍五入方法是否有不良副作用。@Frank。一位客人所说的是坏的副作用请注意,这是有原因的。在试图规避这个问题之前,先考虑它是否是更坏的副作用。请参见仅使用
repr
(或等效格式)查看
浮点的所有相关数字。我不同意
四舍五入(-1.225,2)
应为
-1.22
。这个参数实际上更接近于
-1.23
(因为十进制数被四舍五入到最接近的
float
,就像任何其他这样的文字一样)。它不是一个四舍五入函数用来猜测给定数字的原点的地方。你可以考虑一个<代码> Roop-Mix-UpUp(“-1.225”,2),这将有足够的信息来选择-1.22作为结果;当然,@daviserring
repr
将在执行
float(repr(x))
时显示尽可能多的数字,以获得相同的二进制表示形式(即,从(无限)多个这样做的数字中选择最短的选项)。因此,
repr
可能会掩盖浮点文本存储为与文本不同的数字(十进制数字)。我从来没有说过,向上取整(-1.225,2)
应该返回
-1.22
,这不应该是因为浮点数学。然而,对于用户来说,
-1.225
很可能意味着十进制数,因此他们可能期望
向上取整半个
返回
-1.22
。还要注意,取整模式独立于浮点数学实现。因此,当用户说要将
-1.225
四舍五入(作为十进制数)时,结果应该是
-1.22
。恰好,当将
-1.225
存储为IEEE 754 64位浮点时,由于浮点错误,结果会有所不同。我完全理解这一点。我想用
repr
而不是
.20