【问题标题】:Generate two random numbers whose square sum ==1生成两个平方和 ==1 的随机数
【发布时间】:2019-05-08 18:51:01
【问题描述】:

您好,我想生成两个随机数,使它们的平方和等于 1。

我已经写了这段代码。它们的平方和可能不完全等于 1,但应该接近 0.999。我也用过if(math.isclose(abs(gene_value_1)**2 + abs(gene_value_2)**2, 1)),但是没用。

gene_value_1 = random.uniform(0, 1)
gene_value_2 = random.uniform(0, 1)
if(abs(gene_value_1)**2 + abs(gene_value_2)**2) == 1:
    print(added)

我想生成两个随机数,它们的平方和几乎等于 1。

【问题讨论】:

  • cos(angle)sin(angle)[-pi, pi] 中随机选择一个角度怎么样?
  • 您的问题陈述不一致。如果你的条件是它们的平方和是 1.0,那么你就没有两个随机数:你有一个随机数,第二个是从第一个随机数导出的。您是否尝试随机拍摄,并发现您是否已接近到单位圆?
  • 取 1 个介于 0 和 1 之间的随机数,对其平方,从 1 中减去平方值并求其平方根...你会很幸运生成两个随机数并希望它们的平方加起来 1

标签: python numpy random geometry


【解决方案1】:

您的要求实际上并不是针对两个不同的数字。它适用于平方和等于 1 的一对数字。

如果x**2 + y**2 = 1,那么y完全由x决定:y = sqrt(1 - x**2)

gene_value_1 = random.uniform(0, 1)
gene_value_2 = math.sqrt(1.0 - gene_value_1**2)

正如问题和这个答案的 cmets 中所提到的,以这种方式获得的分布对于这两个数字是不均匀的。由于gene_value_1gene_value_2 将在统一情况下描述笛卡尔空间中的单位圆,您可以这样做

angle = random.uniform(0, 2 * math.pi)
gene_value_1 = math.cos(angle)
gene_value_2 = math.sin(angle)

【讨论】:

  • 虽然这可以满足要求的问题,但值得注意的是,结果分布在 x 和 y 之间是不对称的。大部分时间gene_value_2 会大于gene_value_1 (1/sqrt(2) ~ 0.71)
  • @MarkDickinson 在上面的 cmets 中建议的极坐标方法更好。它会生成均匀分布在单位圆上的 x,y 点,而此方法不会。
  • 上述两个cmets都提到了一个公平的观点,我认为这应该作为注释包含在答案中。
  • @kmario。添加了一个额外的附录。
  • 现在看起来不错?感谢更新!我建议的原因是不是每个人都阅读 cmets 部分,特别是当答案被 OP 接受时。 + 1
【解决方案2】:

我非常感谢 Mark Dickinson's suggestion 使用三角函数生成两个平方和为 1 的随机数。这是最重要的三角恒等式之一,有时被称为 正弦和余弦的毕达哥拉斯公式强>

sine^2 (theta) + cos^2(theta) = 1

因此,我们在区间[-pi, pi] 中随机抽样theta 并取其中的sinecosine。这给了我们两个数字,当它们独立平方然后相加时将等于 1。

所以,实现看起来像:

def squared_unity():
    r = np.random.uniform(-np.pi, np.pi)
    r1, r2 = np.cos(r), np.sin(r)
    # sanity check
    sq_sum = np.sum(np.square([r1, r2]))
    print("the two random numbers are: {}, {}".format(round(r1, 4), round(r2, 4)))
    print("sum of the squares of them is: {}".format(round(sq_sum, 4)))

In [172]: for i in range(10): 
     ...:     squared_unity() 

the two random numbers are: -0.4232, 0.906
sum of the squares of them is: 1.0
the two random numbers are: -0.6432, 0.7657
sum of the squares of them is: 1.0
the two random numbers are: -0.9854, 0.1701
sum of the squares of them is: 1.0
the two random numbers are: 0.6192, -0.7852
sum of the squares of them is: 1.0
the two random numbers are: 0.613, 0.7901
sum of the squares of them is: 1.0
the two random numbers are: 0.3289, -0.9444
sum of the squares of them is: 1.0
the two random numbers are: -0.6289, -0.7775
sum of the squares of them is: 1.0
the two random numbers are: 0.5851, 0.811
sum of the squares of them is: 1.0
the two random numbers are: -0.9515, 0.3076
sum of the squares of them is: 1.0
the two random numbers are: 0.992, -0.1258
sum of the squares of them is: 1.0

【讨论】:

    【解决方案3】:

    生成两个随机数,它们的平方和接近 等于 1。

    假设几乎相等意味着一些小的增量

    delta = 0.00000000001
    gene_value_1 = random.uniform(0,1)
    gene_value_2 = math.sqrt(1.0 - gene_value_1**2)
    gene_value_2 = random.uniform(gene_value_2-delta,gene_value_2+delta)
    

    【讨论】:

      【解决方案4】:

      isclose 的默认容差为 10^-9;这可能对您的目的来说太紧了。由于您没有指定问题,我将尝试一个完全不使用该功能的版本:

      import random
      
      tol = 0.01    # Tolerance: how close to 1.0 do we have to be?
      
      # For illustration, try 1000 times; only a few will get close enough.
      for _ in range(1000):
          gene_value_1 = random.uniform(0, 1)
          gene_value_2 = random.uniform(0, 1)
          if abs((gene_value_1**2 + gene_value_2**2) - 1.0) < tol:
              print(gene_value_1, gene_value_2)
      

      输出:

      0.494788483232363 0.8684265825591323
      0.2534457849885592 0.9641226120957478
      0.7203139196461331 0.6907040618050416
      0.5209764827501758 0.8494629588837268
      0.35131722626502326 0.9326863439646066
      0.9090058297727053 0.41193607685541955
      0.38668550268554913 0.9211652839586227
      0.4981396919166827 0.8716609641505723
      0.32335194126436084 0.9515174500031403
      0.8975054159419422 0.4338981696304519
      0.9055370877201422 0.4174842572890476
      0.6174536739530609 0.789563981024344
      0.8238168460048567 0.564248521210536
      0.8086540730748032 0.5877591346132056
      0.9483222364877975 0.3290608007951834
      0.7610944343401178 0.6448728614809394
      0.9909209668202087 0.1333222757510487
      0.985161966125415 0.16537725793380365
      0.39363133060821665 0.9232464739964449
      

      【讨论】:

        【解决方案5】:

        如果您想要两个平方和为 1 的值,已经提出的基于几何的建议非常好,即在 [0,2π) 上均匀生成角度 θ 并使用正弦 (θ) 和余弦 (θ)。但是,如果您想扩展到更高的维度,这种方法很快就会变得令人讨厌。

        推广到任意维数的一个不错的替代方法是生成独立的高斯并对其进行归一化。 N 个独立的多元高斯可以表示为一个 N 维向量,该向量同样可能指向 N 空间中的任何方向。生成向量,将其长度标准化为 1.0,瞧!即时平方和 == 1。如果您希望平方和接近 1 但不相等,您可以随机化标准化比例因子。

        from functools import reduce
        from math import sqrt
        from random import gauss, uniform
        
        def sum_of_squares_is_one(n = 2):
            if ((n < 2) or (int(n) != n)) is True:
                raise Exception("Invalid argument for n")
            l = [gauss(0.0, 1.0) for _ in range(n)]
            norm = sqrt(reduce(lambda sum,x: sum + x*x, l, 0.0)) # / uniform(0.95, 1.05)
            return [x / norm for x in l]
        
        print(sum_of_squares_is_one())
        # => [-0.5507487065788466, -0.8346711101995371]
        print(sum_of_squares_is_one(5))
        # => [-0.5985784458250389, 0.3741123562198886, -0.2600006068118713, -0.5415988718467569, 0.37525209604886034]
        

        n 传递一个显式参数以获得N 维结果。 如果您想获得平方和在 [0.95, 1.05] 内的值,请取消注释除以制服,或根据需要调整范围。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-30
          • 1970-01-01
          • 2017-07-25
          • 2022-05-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多