我正在寻找一种方法,根据从小数点后的数字得出的概率将浮点数向上或向下舍入到下一个整数。例如,浮点数 6.1 可以四舍五入到 6 和 7。蜜蜂四舍五入到 7 的概率是 0.1,四舍五入到 6 的概率是 1-0.1。所以如果我无限次地运行这个舍入实验,所有整数结果的平均值应该又是 6.1。我不知道这样的过程是否有名称,以及 Python 中是否已经存在并实现了函数。当然,如果可以用同样的方法四舍五入到小数点后 2 位,那就太好了。
那有意义吗?有任何想法吗?
我正在寻找一种方法,根据从小数点后的数字得出的概率将浮点数向上或向下舍入到下一个整数。例如,浮点数 6.1 可以四舍五入到 6 和 7。蜜蜂四舍五入到 7 的概率是 0.1,四舍五入到 6 的概率是 1-0.1。所以如果我无限次地运行这个舍入实验,所有整数结果的平均值应该又是 6.1。我不知道这样的过程是否有名称,以及 Python 中是否已经存在并实现了函数。当然,如果可以用同样的方法四舍五入到小数点后 2 位,那就太好了。
那有意义吗?有任何想法吗?
您正在寻找的概率是x-int(x)
。
要以这种概率进行采样,请执行random.random() < x-int(x)
import random
import math
import numpy as np
def prob_round(x):
sign = np.sign(x)
x = abs(x)
is_up = random.random() < x-int(x)
round_func = math.ceil if is_up else math.floor
return sign * round_func(x)
x = 6.1
sum( prob_round(x) for i in range(100) ) / 100.
=> 6.12
编辑:添加一个可选prec
参数:
def prob_round(x, prec = 0):
fixup = np.sign(x) * 10**prec
x *= fixup
is_up = random.random() < x-int(x)
round_func = math.ceil if is_up else math.floor
return round_func(x) / fixup
x = 8.33333333
[ prob_round(x, prec = 2) for i in range(10) ]
=> [8.3399999999999999,
8.3300000000000001,
8.3399999999999999,
8.3300000000000001,
8.3300000000000001,
8.3300000000000001,
8.3300000000000001,
8.3300000000000001,
8.3399999999999999,
8.3399999999999999]
这是一个很好的单线。通过使用 floor 函数,只有在 0 和 1 之间的随机数足以将其提升到下一个最高整数时,才会将其向上取整。此方法同样适用于正数和负数。
def probabilistic_round(x):
return int(math.floor(x + random.random()))
考虑负输入的情况x = -2.25
。75% 的时间随机数将大于或等于 0.25,在这种情况下,地板函数将导致 -2 为答案。其他 25% 的时间该数字将向下舍入为 -3。
要四舍五入到不同的小数位,可以修改如下:
def probabilistic_round(x, decimal_places=0):
factor = 10.0**decimal_places
return int(math.floor(x*factor + random.random()))/factor
对非负 x 执行此操作的最简洁方法是:
int(x + random.random())
例如,如果x == 6.1
,那么有 10% 的机会random.random()
足以使x + random.random() >= 7
.
请注意,如果x == 6
,则该表达式保证返回6
,因为random.random()
始终在 [0, 1) 范围内。
更新:此方法仅适用于非负输入。有关适用于负数的解决方案,请参阅 Chris Locke 的回答。
要将正值四舍五入为整数,您可以非常简洁地执行此操作:
x = int(x) + (random.random() < x - int(x))
这是有效的,因为 Python 的bool
类型是int
. 该值True
等于 1 和False
等于 0。
我还提出了一个基于 random 的二项式函数和 shx2 已经提供的代码的解决方案:
def prob_round(x, prec = 0):
fixup = np.sign(x) * 10**prec
x *= fixup
round_func = int(x) + np.random.binomial(1,x-int(x))
return round_func/fixup
这是一个简单的方法:
x = round(random.random()*100)
该*100
位表示 1 到 100。
如果*200
,则表示 1 到 200。