我正在尝试从python标准库实现我自己的Random class版本。我可以生成随机位,并实现了getrandbits(n)函数。但是超类不使用此函数来计算random()返回的浮点值。所以我必须自己去实现:
def random(self):
exp = 0x3FF0000000000000
mant = self.getrandbits(52)
return struct.unpack("d", struct.pack("q", exp^mant))[0]-1.0
我使用的符号是0(正),指数是1023(2^0=1)和随机尾数。所以我从[1.0,2.0]中得到一个数字。random()函数必须返回一个[0.0,1.0)的数字,所以我在返回之前减去1.0。 由于我不是浮点数方面的专家,我不确定这是否正确。我不是因为减法而失去精确性吗?我能从随机位构造这个数字,使它在[0.0,1.0)内而不做减法吗?在
您的实现很好:假设}上均匀分布的一个很好的近似值。你使用的减法不是问题:减法的结果总是精确地表示出来的,因此减法不会涉及舍入或精度损失。在
getrandbits
本身足够随机,那么您的实现将以相等的概率为0 <= n < 2^52
生成n / 2^52
形式的每个数,因此这是{Python的
random()
实现在return self.getrandbits(53) / 2**53.
的路线上做了更多的事情,效果相似,只是输出的分布现在是原来的两倍:您以相等的概率获得n / 2^53
形式的每个数。在实践中,大多数应用程序不太可能注意到这两种实现之间的差异。如果你关心的是速度,它很可能也更快,尽管你应该像往常一样侧写,看看是否真的是这样。在这两种方法都不是完美的:在
[0.0, 1.0)
范围内有大约2^62
个不同的ieee754二进制64浮点,而您的实现只能生成2^52
个不同的输出,因此这些浮动中的大多数永远不能由上述实现中的任何一个生成。一个更好的random()
实现可以在[0.0, 1.0]
范围内生成每个浮点数x
,其概率等于某种形式的舍入到x
的子区间的长度。然而,这样的实现将更加复杂(尽管不是特别难实现),并且很少有应用程序能够从更大的输出集中获益。正如Python禅宗所说:“实用性胜过纯洁性。”编辑:为了说明上面最后一段,这里有一些代码。根据上述描述,}上生成均匀分布的浮动。在
uniform
函数使用getrandbits
在{相关问题 更多 >
编程相关推荐