[英]How to generate scale-independent random floating point numbers?
I want to generate what I'm choosing to call "arbitrary" positive floating-point numbers; 我想生成我选择称之为“任意”正浮点数的东西; that is, random numbers which are independent of scale (in other words, numbers whose logarithms are uniformly distributed).
也就是说,随机数与尺度无关(换句话说,是对数均匀分布的数字)。 I'm not much of a mathematician, so for all I know there may be another name for what I'm after.
我不是一个数学家,所以我知道我可能会有另一个名字。
Here's my initial, naïve solution: 这是我最初的,天真的解决方案:
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)
It strikes me that this is probably not ideal: for one thing, I imagine that there might be some interaction between the limited precision of random.uniform()
and the floating point representation itself that would cause bunching and gaps in the expected output at higher orders of magnitude. 令我感到
random.uniform()
是,这可能并不理想:首先,我认为random.uniform()
的有限精度与浮点表示本身之间可能存在一些相互作用,这会导致预期输出中的聚束和间隙更高数量级。
Is there a better approach? 有更好的方法吗?
Would it make more sense to just produce a string of random bits and then turn that into the floating point number they represent? 仅生成一串随机位然后将其转换为它们所代表的浮点数会更有意义吗?
EDIT : As pointed out by Oli Charlesworth in the comments, the "convert random bits to a float" idea doesn't do what I want (which is a uniform distribution of log(n)). 编辑 :正如Oli Charlesworth在评论中所指出的那样,“将随机位转换为浮点数”的想法并没有达到我想要的效果(这是log(n)的均匀分布)。
You are correct that your approach doesn't return some numbers. 你是正确的,你的方法不会返回一些数字。 For example, there is no floating-point number between
1.0
and 1.0000000000000002
, but 10**1.0000000000000002
is 10.000000000000005
, and there are two numbers between 10.0
and 10.000000000000005
: 10.000000000000002
and 10.000000000000004
. 例如,
1.0
和1.0000000000000002
之间没有浮点数,但10**1.0000000000000002
是10.000000000000005
,并且10.0
和10.000000000000005
之间有两个数字: 10.000000000000002
和10.000000000000004
。 Those two numbers will never be returned by your algorithm. 算法永远不会返回这两个数字。
But you can cheat and use Decimal
to exponentiate with greater precision: 但你可以作弊并使用
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
So, arbitrary
needs to generate random Decimal
exponents of sufficient precision and use them as exponents. 因此,
arbitrary
需要生成足够精度的随机Decimal
指数并将它们用作指数。 Assuming 64 binary digits is enough precision for the exponent, the code would look like this: 假设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))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.