4

我想生成我选择称之为“任意”正浮点数的东西;也就是说,与尺度无关的随机数(换句话说,对数均匀分布的数字)。我不是一个数学家,所以据我所知,我所追求的可能还有另一个名字。

这是我最初的、幼稚的解决方案:

import sys
import random

def arbitrary(min=sys.float_info.min_10_exp, max=sys.float_info.max_10_exp):
    return 10 ** random.uniform(min, max)

令我震惊的是,这可能并不理想:一方面,我认为有限的精度random.uniform()和浮点表示本身之间可能存在一些相互作用,这会导致更高数量级的预期输出中的聚束和间隙。

有更好的方法吗?只产生一串随机位然后将其转换为它们代表的浮点数会更有意义吗?

编辑:正如 Oli Charlesworth 在评论中指出的那样,“将随机位转换为浮点数”的想法并没有达到我想要的效果(这是 log(n) 的均匀分布)。

4

1 回答 1

1

你是正确的,你的方法没有返回一些数字。1.0例如, and之间没有浮点数1.0000000000000002,但是10**1.0000000000000002is ,并且and :和10.000000000000005之间有两个数。你的算法永远不会返回这两个数字。10.010.00000000000000510.00000000000000210.000000000000004

但是您可以作弊并使用Decimal以更精确地取幂:

>>> float(10 ** Decimal('1'))
10.0
>>> float(10 ** Decimal('1.0000000000000001'))
10.000000000000002
>>> float(10 ** Decimal('1.00000000000000015'))
10.000000000000004
>>> float(10 ** Decimal('1.0000000000000002'))
10.000000000000005

因此,arbitrary需要生成Decimal足够精度的随机指数并将它们用作指数。假设 64 位二进制数字对于指数来说足够精确,代码将如下所示:

import sys, random
from decimal import Decimal

def _random_decimal(minval, maxval, added_prec):
    # generate a Decimal in the range [minval, maxval) with the
    # precision of additional ADDED_PREC binary digits
    rangelen = maxval - minval
    denom = rangelen << added_prec
    return minval + Decimal(rangelen) * random.randrange(denom) / denom

def arbitrary():
    min_exp = sys.float_info.min_exp - sys.float_info.mant_dig
    max_exp = sys.float_info.max_exp
    return float(2 ** _random_decimal(min_exp, max_exp, 64))
于 2013-07-06T22:06:43.413 回答