【问题标题】:How to randomly generate really small numbers?如何随机生成非常小的数字?
【发布时间】:2017-09-07 02:54:31
【问题描述】:

假设我想在 [10^-20, 0.1] 范围内绘制一个随机数,我该怎么做?

如果我使用 numpy.random.uniform,我似乎不会低于 10^-2:

In [2]: np.random.uniform(0.1, 10**(-20))
Out[2]: 0.02506361878539856

In [3]: np.random.uniform(0.1, 10**(-20))
Out[3]: 0.04035553250149768

In [4]: np.random.uniform(0.1, 10**(-20))
Out[4]: 0.09801074888377342

In [5]: np.random.uniform(0.1, 10**(-20))
Out[5]: 0.09778150831277296

In [6]: np.random.uniform(0.1, 10**(-20))
Out[6]: 0.08486347093110456

In [7]: np.random.uniform(0.1, 10**(-20))
Out[7]: 0.04206753781952958

或者,我可以生成一个数组,例如:

In [44]: fac = np.linspace(10**(-20),10**(-1),100)

In [45]: fac
Out[45]: 
array([  1.00000000e-20,   1.01010101e-03,   2.02020202e-03,
         3.03030303e-03,   4.04040404e-03,   5.05050505e-03,
         6.06060606e-03,   7.07070707e-03,   8.08080808e-03,
         9.09090909e-03,   1.01010101e-02,   1.11111111e-02,
         1.21212121e-02,   1.31313131e-02,   1.41414141e-02,
         1.51515152e-02,   1.61616162e-02,   1.71717172e-02,
         1.81818182e-02,   1.91919192e-02,   2.02020202e-02,
         2.12121212e-02,   2.22222222e-02,   2.32323232e-02,
         2.42424242e-02,   2.52525253e-02,   2.62626263e-02,
         2.72727273e-02,   2.82828283e-02,   2.92929293e-02,
         3.03030303e-02,   3.13131313e-02,   3.23232323e-02,
         3.33333333e-02,   3.43434343e-02,   3.53535354e-02,
         3.63636364e-02,   3.73737374e-02,   3.83838384e-02,
         3.93939394e-02,   4.04040404e-02,   4.14141414e-02,
         4.24242424e-02,   4.34343434e-02,   4.44444444e-02,
         4.54545455e-02,   4.64646465e-02,   4.74747475e-02,
         4.84848485e-02,   4.94949495e-02,   5.05050505e-02,
         5.15151515e-02,   5.25252525e-02,   5.35353535e-02,
         5.45454545e-02,   5.55555556e-02,   5.65656566e-02,
         5.75757576e-02,   5.85858586e-02,   5.95959596e-02,
         6.06060606e-02,   6.16161616e-02,   6.26262626e-02,
         6.36363636e-02,   6.46464646e-02,   6.56565657e-02,
         6.66666667e-02,   6.76767677e-02,   6.86868687e-02,
         6.96969697e-02,   7.07070707e-02,   7.17171717e-02,
         7.27272727e-02,   7.37373737e-02,   7.47474747e-02,
         7.57575758e-02,   7.67676768e-02,   7.77777778e-02,
         7.87878788e-02,   7.97979798e-02,   8.08080808e-02,
         8.18181818e-02,   8.28282828e-02,   8.38383838e-02,
         8.48484848e-02,   8.58585859e-02,   8.68686869e-02,
         8.78787879e-02,   8.88888889e-02,   8.98989899e-02,
         9.09090909e-02,   9.19191919e-02,   9.29292929e-02,
         9.39393939e-02,   9.49494949e-02,   9.59595960e-02,
         9.69696970e-02,   9.79797980e-02,   9.89898990e-02,
         1.00000000e-01])

并从该数组中选择一个随机元素,但无论如何我想澄清第一个选项是否可行,因为我可能会遗漏一些明显的东西。

【问题讨论】:

  • 其实我不懂python,但每种语言的逻辑都是一样的。生成 10^10 到 10^11 之间的随机数,然后除以 10^12
  • 我认为你错过了你的问题的统计数据......在均匀分布的情况下,达到数字 10^-20 的机会微乎其微。你想要一个日志分发而不是?
  • 这是一个很酷的主意!我只是用任意平均值和 sigma 尝试了 numpy.random.lognormal,我得到的值非常低。不过,为这些参数找到正确的值是很重要的。
  • @jkrish:请注意,分布会有很大偏差。您想要均匀分布还是想要极有可能的低值?
  • 在 [0.1, 10^-20] 范围内的均匀分布。我猜亚历克斯设置低、非常低的答案效果最好!?

标签: python python-3.x numpy random


【解决方案1】:

您需要仔细考虑自己在做什么。您要求在几乎 0.0 和 0.1 之间进行均匀分布。平均结果为 0.05。这正是你得到的。看来您想要指数的随机分布。

以下可能会满足您的需求:

import random

def rnd():
    exp = random.randint(-19, -1)
    significand = 0.9 * random.random() + 0.1
    return significand * 10**exp

[rnd() for _ in range(20)]

exp=-19significand=0.1 给出0.1*10**-19 = 1**-20 时,可能的最低值。而可能的最高值是exp=-1significand=1.0 给出1.0*10**-1 = 0.1

注意:从技术上讲,significand 只能接近 1.0 为 random() is bounded to [0.0, 1.0),即包括 0.0,但不包括 1.0。

输出:

[2.3038280595190108e-11,
 0.02658855644891981,
 4.104572641101877e-11,
 3.638231824527544e-19,
 6.220040206106022e-17,
 7.207472203268789e-06,
 6.244626749598619e-17,
 2.299282102612733e-18,
 0.0013251357609258432,
 3.118805901868378e-06,
 6.585606992344938e-05,
 0.005955900790586139,
 1.72779538837876e-08,
 7.556972406280229e-13,
 3.887023124444594e-15,
 0.0019965330694999488,
 1.7732147730252207e-08,
 8.920398286274208e-17,
 4.4422869312622194e-08,
 2.4815949527034027e-18]

有关有效数和指数的定义,请参阅维基百科上的“scientific notation”。

【讨论】:

    【解决方案2】:

    如果您在 [0,0.1] 范围内生成均匀随机数,则出现小于 10^-20 的随机数的可能性是 10^-19 分之一。它可能永远不会发生。但是,如果您必须确保它不会发生(可能是因为较小的数字会使您的代码崩溃),那么只需在 [0] 范围内生成统一随机数,0.1],测试它们,并通过用来自同一生成器的另一个统一随机数替换它们并重新测试来拒绝任何太小。这将“非常不可能”替换为“肯定不会发生”。

    这种技术在蒙特卡洛模拟中更常见,您希望随机采样 f(x,y) 或 f(x,y,z),其中坐标 (x,y[,z]) 必须在一些具有复杂定义的区域或体积,例如复杂机械部件的内部。技术是一样的。建立边界范围 [xlow, xhigh], [ylow, yhigh] ...并在此边界框内生成均匀分布的随机坐标。然后检查这个随机位置是否在要采样的区域/体积内。如果不是,则生成另一个随机元组并重新检查。

    【讨论】:

      【解决方案3】:

      由于您想保持均匀分布并避免与浮点表示相关的问题,只需在 0 和 9 之间均匀绘制 20 个整数,然后使用以 10 为底的表示“构建”您的结果(您仍然会有均匀分布):

      result = 0
      digits = np.random.randint(0,10,20)
      for idx,digit in enumerate(digits):
        result += digit*(10**idx)
      

      这将为您提供一个介于 0 和 10**19 -1 之间的数字。您可以对结果进行不同的解释以获得您想要的结果。

      【讨论】:

        【解决方案4】:

        根据 numpy 文档:

        low : 浮点数或类似数组的浮点数,可选 输出区间的下边界。生成的所有值都将大于或等于低。默认值为 0。

        考虑到这一点,减少low 的值会产生较小的数字

        >>> np.random.uniform(0.00001, 10**(-20))
        6.390804027773046e-06
        

        【讨论】:

        • 你不是在减少low,而是在减少high。值不会高于1E-5,你永远不会达到0.1
        • @EricDuminil 以numpy.random.uniform(low=0.0, high=1.0, size=None) 为函数定义,那肯定是减低了?同样来自文档:“如果高
        • @NickA:是的,应该颠倒顺序。仍然:max(np.random.uniform(0.00001, 10**(-20)) for _ in range(10000000)) 返回9.999999414469333e-06,所以看起来0.00001 被解释为high
        • 这个答案不跨越 [10^-20, 0.1] 它仅限于 [10^-5, 10^-6]。另外,我很惊讶这没有引发错误。由于high 设置为低于low。 “如果高docs.scipy.org/doc/numpy/reference/generated/…
        • 我现在在 cmets 中看到,它的目的是让参数反向。然后该解决方案将起作用,但仍限于 [10^-20, 10^-5],平均约为 0.5*10^-6。它可能永远不会看到低于 10^-7 的任何东西。也就是说,OP 似乎很好。
        【解决方案5】:

        如何生成一个介于 1 到 10 000 之间的随机数, 然后将该数字除以 100 000。

        【讨论】:

        • 这是我的直接想法,虽然它不会介于 1 和 10000 之间,但它会是 11e19 之间的数字除以 1e20
        • 如果您想要实际跨越 [10^-20, 0.1] 并获得非常低的数字,那么这是错误的答案。如果使用均匀分布,这将主要生成大约 0.05(平均值)的数字,就像 OP 已经拥有的那样。你永远不会看到像 10^-19 或 10^-20 这样的数字。
        • @AndréChristofferAndersen 是的,但强制数字向 10^-20 和 0.1 移动则不是随机的
        • @NickA 这是完全随机的。只是不均匀随机。 OP 要求在 [10^-20, 0.1] 范围内的数字,这意味着一些结果应该接近数量级的下限。如果不是,那么设置这样的下限是没有意义的。
        • 还不如将return 0.05 夹在一个函数中;)
        猜你喜欢
        • 2011-07-23
        • 2014-09-03
        • 1970-01-01
        • 1970-01-01
        • 2011-07-03
        • 1970-01-01
        • 1970-01-01
        • 2013-03-03
        • 2015-11-30
        相关资源
        最近更新 更多