我想生成一个随机数n,使其n在范围内(a,b)或(a,b]在哪里a < b.这在python中可能吗?似乎唯一的选择a + random.random()*(b-a)是包含[a,b)或random.uniform(a,b)包括范围,[a,b]因此既不符合我的需要.
计算机生成"随机"数字是棘手的,特别是"随机"浮点数.你需要长时间地思考你真正想要的东西.最后,你需要在整数之上构建一些东西,而不是直接用浮点数构建.
在Python中(以及使用Mersenne Twister的源代码的所有其他语言),生成"随机"IEEE-754双(Python的基本random.random())实际上是通过生成随机53位整数,然后除以2**53来实现的. :
randrange(2**53) / 9007199254740992.0
Run Code Online (Sandbox Code Playgroud)
这就是为什么输出范围是[0.0, 1.0),但并非所有可表示的浮动在该范围内同样可能.只有可以在I/2**53整数形式中表达的那些0 <= I < 2**53.例如,1.0 / 2**60永远不会返回浮点数.
这里没有"实数",只是可表示的二进制浮点数,所以要回答你的问题首先要求你指定你想要选择的那些的确切集合.
如果答案是你不想那么挑剔,那么开放和封闭之间的区别也太挑剔而无法理解.如果您可以指定精确集,那么解决方案是生成映射到输出集的或多或少明显的随机整数.
例如,如果要在小数点后仅2位从[3.0,6.0]中选择"随机"浮点数,则有13个可能的输出.所以第一步是
i = random.randrange(13)
Run Code Online (Sandbox Code Playgroud)
然后映射到感兴趣的范围:
return 3.0 + i / 4.0
Run Code Online (Sandbox Code Playgroud)
正如在评论中指出,所有表示的统一采摘彩车x用0.0 < x < 1.0可以做到的,但是从很远均匀分布跨越该范围.例如,有可2**52表示的浮点数[0.5, 1.0),但也有可2**52表示的浮点数[0.25, 0.5),并且...... [2.0**-i, 2.0**(1-i))进行增加,i直到我们达到低于正常范围时可表示的浮点数开始收缩,当我们完全下溢到0时最终降到无.
然而,作为位模式,它们非常简单:(0, 1)当将位模式视为整数时,可表示的IEEE-754双精度集(几乎所有平台上的Python浮点数)都包含在内
range(1, 0x3ff0000000000000)
Run Code Online (Sandbox Code Playgroud)
因此,生成具有相同可能性的每个函数的函数可以直接使用比特填充技巧进行编写:
from struct import unpack
from random import randrange
def gen01():
i = randrange(1, 0x3ff0000000000000)
as_bytes = i.to_bytes(8, "big")
return unpack(">d", as_bytes)[0]
Run Code Online (Sandbox Code Playgroud)
只运行几次,看看为什么它没用 - 它非常偏向于范围的0.0端:
>>> for i in range(10):
... print(gen01())
9.796357610869274e-104
4.125848254595866e-197
1.8114434720880952e-253
1.4937625148849258e-285
1.0537573744489343e-304
2.79008159472542e-58
4.718459887295062e-217
2.7996009087703915e-295
3.4129442284798105e-170
2.299402306630583e-115
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
421 次 |
| 最近记录: |