【发布时间】:2020-10-01 18:59:02
【问题描述】:
我想要一个函数(如果相关,则使用 Python 3.6+),它会以下列方式将浮点数随机四舍五入为整数:
给定一个实数x,让a = floor(x) 和b = ceil(x)。然后,编写一个函数s_int(),它将以b - x 的概率返回a,并以x - a 的概率返回b。
例如,s_int(14.8) 应该在 20% 的时间返回 14,在剩余的 80% 的时间返回 15。
这是我的尝试:
import math
from random import random
def s_int(x):
a = math.floor(x)
return a + ((x - a) > random())
它似乎适用于我能想到的所有情况:
In [2]: Counter(s_int(14.7) for _ in range(1000000))
Out[2]: Counter({14: 300510, 15: 699490})
In [3]: Counter(s_int(-14.7) for _ in range(1000000))
Out[3]: Counter({-15: 700133, -14: 299867})
In [4]: Counter(s_int(14) for _ in range(1000000))
Out[4]: Counter({14: 1000000})
In [5]: Counter(s_int(-14) for _ in range(1000000))
Out[5]: Counter({-14: 1000000})
In [6]: Counter(s_int(0) for _ in range(1000000))
Out[6]: Counter({0: 1000000})
这是我的问题:
有没有我认为这个函数不起作用的边缘情况?
还有其他更简单或更优雅的解决方案吗?
可以让它运行得更快吗?
【问题讨论】:
-
@XYZT 我猜你是对的。
-
应该是
return a + ((x - a) >= random())?random包括 0.0 但不包括 1.0。 Python 的浮点数有 52 位尾数,因此天花板下的最大数字永远不会用您的方法输出地板。我有点认为你有 1 到 52 位的偏差。如果我是对的,你的火箭将与火星相距相当远。当然,如果你改变它,1.0将每隔一段时间发出2。我要彻底放弃火星飞行了。 -
@tdelaney:Python 没有指定浮点格式,除非最近发生了变化。许多实现使用 IEEE-754 binary64。该格式的有效位,而不是尾数,有 53 位。 52 被编码在主要有效位字段中,1 被编码在指数字段中。对于 1 以下的最大可表示数(称为 g),使用
>产生的结果永远不会是上限。但是,对于大于 1 的上限,上限下的最大可表示数字有时会返回上限,因为 x-floor(x) 小于 g,因为 x 处的 ULP 更大。 -
@tdelaney:
(x - a) > random()还具有对精确整数执行正确操作的优点:如果x是精确整数,x - a将精确为零,所以@987654343 @ 永远不会是真的,我们将永远“四舍五入”到x本身。用>=代替>,x = 14.0有可能被四舍五入到15.0。
标签: python python-3.x floating-point integer rounding