为组合浮点数随机。随机()在Python中

2024-07-08 10:09:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试从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)内而不做减法吗?在


Tags: 函数self版本标准returndef数字random
1条回答
网友
1楼 · 发布于 2024-07-08 10:09:50

您的实现很好:假设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在{}上生成均匀分布的浮动。在

"""                                                                                                                                                                                                                                         
High quality uniform random variable on [0, 1].                                                                                                                                                                                             

Simulates round(X) where X is a real random variable uniformly distributed on                                                                                                                                                               
the interval [0, 1] and round is the usual round-to-nearest rounding function                                                                                                                                                               
from real numbers to floating-point.                                                                                                                                                                                                        

"""
from __future__ import division
import random

precision = 53
emin = -1021

def random_significand():
    return (random.getrandbits(precision) + 1) // 2 / (2**precision)

def uniform():
    for i in xrange(1 - emin):
        if random.getrandbits(1):
            return (random_significand() + 0.5) / 2**i
    # Subnormal                                                                                                                                                                                                                             
    return random_significand() / 2**i

相关问题 更多 >

    热门问题