Vba Excel';s随机数发生器不是随机的吗?

Vba Excel';s随机数发生器不是随机的吗?,vba,excel,testing,statistics,Vba,Excel,Testing,Statistics,我正在测试Excel的随机生成器是否真的是随机的,这就是为什么我要使用它 通过这样做,我得到了一个p值0,因此我不接受空值,即样本不是随机的 我的问题是: 1) 我是否在编码或解释方面犯了一些错误? 代码: 胡里奥·耶苏·卢娜·莫雷诺的《代码》 'jlqmoreno@gmail.com 选项基数1 子测试() Dim x,r(),i,n,mu,sigma,plus(),minus(),k,h,f,j,phi,rplus,rmius,rachas()作为变量 Dim w为双精度,标志为布尔值 n=

我正在测试Excel的随机生成器是否真的是随机的,这就是为什么我要使用它

通过这样做,我得到了一个p值0,因此我不接受空值,即样本不是随机的

我的问题是:

1) 我是否在编码或解释方面犯了一些错误?

代码:

胡里奥·耶苏·卢娜·莫雷诺的《代码》 'jlqmoreno@gmail.com 选项基数1 子测试() Dim x,r(),i,n,mu,sigma,plus(),minus(),k,h,f,j,phi,rplus,rmius,rachas()作为变量 Dim w为双精度,标志为布尔值 n=1000:k=0:h=0:flag=False:rplus=0:rminus=0:j=0:phi=0 Set f=Application.WorksheetFunction 雷迪姆r(n) 对于i=1到n 随机化 x=Rnd() r(i)=IIf(x>=0.5,1,0) 调试.打印r(i) 接下来我 k=r(1) h=2 边做边做 如果r(h)=k,则 φ=φ+1 flag=False h=h+1 其他的 flag=True k=r(h) h=h+1 如果结束 环 如果φ>=1,则 j=j+1 雷迪姆·拉卡斯(j) 拉卡斯(j)=r(h-2) 调试.打印rachas(j) 如果结束 flag=False φ=0 环 rplus=j-f.Sum(rachas) rminus=j-rplus mu=((2*rplus*rmius)/j)+1 西格玛=(μ-1)*(μ-2)/(j+1) w=f.Norm\u S\u Dist((j-mu)/Sqr(sigma),假) 调试 端接头 提前谢谢

  • Excel的随机数生成器不是随机的——它只是伪随机的。(大多数计算机生成的随机数也是如此。)

  • 尽管在大多数情况下,随机数通常是足够随机的,但如果您编写一些代码,例如:

    Sub RndTest()
        Dim r(0 To 9999, 0 To 9999) As Long
        Dim i As Long
        Dim x As Long
        Dim y As Long
        For i = 1 To 100000000
            x = Int(Rnd() * 10000)
            y = Int(Rnd() * 10000)
            r(x, y) = r(x, y) + 1
        Next
        Cells(1, 1).Resize(10000, 10000).Value = r
        Columns("A:NTP").AutoFit
    End Sub
    
    在运行该代码时,您需要有点耐心,因为它将生成100000000对随机数,并将它们分配给100000000个单元格。但是最后产生的图案看起来很好看

    很多问题都是由于VBA中生成的随机数只是一个
    单精度
    数字,它只包含大约6个有效数字


    • 你也可以通过掷硬币来测试它

      下面是一个测试这一点的快速代码(不是最好的,但按预期工作):


      您需要对代码进行更正。你对mu的计算不正确

      mu = ((2 * f.Count(plus) + f.Count(minus)) / n) + 1
      
      应该是

      mu = ((2 * f.Count(plus) * f.Count(minus)) / n) + 1
                               ^
                               Note the change here
      

      我认为您的随机化命令也应该在for/next循环之外和之前执行。我不确定这将如何影响结果。

      这是如何实施的

      1-我们计算跑步次数;每次观察到拾取值中的翻转时递增

      2-我们根据独立性假设(无效假设)对应的正态分布检查结果运行次数。准确地说,我们希望获得的运行次数与平均值相差“那么远”。注:这是一项双尾测试

      3-要计算此概率,应使用累积正态分布,即将参数
      cumulative
      设置为
      true

      Sub WaldWolfowitz()
        Randomize
        Dim nRuns As Long ' counts the number of runs
        Dim x As Long ' a randomly picked value, 0 or 1
        Dim lastX As Long: lastX = -1 ' memorizes the last picked value to count runs
        Dim N(0 To 1) As Long ' array holds the number of picks of 0 and 1
      
        Dim i As Long, r As Double
        For i = 1 To 1000000
          r = Rnd
          x = IIf(r < 0.5, 0, 1)
          N(x) = N(x) + 1
          If x <> lastX Then nRuns = nRuns + 1
          lastX = x
        Next
      
        ' Distribution of the number of runs in the case
        ' the picks are independent (the null hypothesis)
        Dim mu As Double, variance As Double, sigma As Double, p As Double, z As Double
        mu = 1 + ((2 * N(0)) / (N(0) + N(1))) * N(1) ' rewrote it this way to avoid overflow
        variance = (mu - 1) * (mu - 2) / (N(0) + N(1) - 1)
        sigma = Sqr(variance)
      
        ' The p-test. We calculate the likelihood that the resulted number of runs
        ' be "that far" from mu. Notice in the calculation below:
        ' - We compute the absolute value of diff because it's a "two-tailed test"
        ' - We calculate the "tail" area under the normal curve from that point
        '   and we multiply it by two
        ' - The parameter "Cumlative:=True" for Norm_S_Dist to calculate the area under the normal curve
        z = Abs(nRuns - mu) / sigma
        p = 2 * (1 - WorksheetFunction.Norm_S_Dist(z, True))
      
        Debug.Print mu, sigma, nRuns, z, p
      End Sub
      
      Sub-WaldWolfowitz()
      随机化
      Dim nRuns As Long“计算运行次数
      将x变长为随机选取的值,0或1
      Dim lastX As Long:lastX=-1'记忆上次拾取的值以计算运行次数
      Dim N(0到1)只要“Long”数组包含0和1的拾取数
      暗淡的i和长的一样,r和双的一样
      对于i=1到1000000
      r=Rnd
      x=IIf(r<0.5,0,1)
      N(x)=N(x)+1
      如果x lastX,则nRuns=nRuns+1
      lastX=x
      下一个
      '案例中运行次数的分布
      “选择是独立的(无效假设)
      Dim mu为双精度,方差为双精度,西格玛为双精度,p为双精度,z为双精度
      mu=1+((2*N(0))/(N(0)+N(1))*N(1)”以这种方式重写它以避免溢出
      方差=(mu-1)*(mu-2)/(N(0)+N(1)-1)
      西格玛=Sqr(方差)
      “p检验。我们计算得出的运行次数
      "离穆"那么远"。请注意以下计算:
      -我们计算差异的绝对值,因为它是一个“双尾测试”
      -我们从该点计算法向曲线下的“尾部”面积
      我们把它乘以二
      '-用于Norm_S_Dist计算法向曲线下面积的参数“cummative:=True”
      z=Abs(nRuns-mu)/sigma
      p=2*(1-工作表功能规范S_区(z,真))
      调试。打印mu,sigma,nRuns,z,p
      端接头
      

      p、 我将让您运行测试并解释它们。我自己的测试并没有拒绝独立性的零假设,尽管我对它们不太满意…

      增量缩进有什么原因吗?@ThunderFrame没有,我只是觉得它看起来很不错,“Dim x,r(),I,n,mu,sigma,plus(),minus(),k,h,f,mediana作为变量”,只有最后一个变量被显式声明。其他的都是隐式变体。这是我以前犯过的错误。@IvenBach我已经纠正了这个错误。你误解了Wald的测试。@Moreno-还有,FWIW,“标准偏差”是“方差”的平方根。你知道有哪种编程语言有“真实”随机数生成器吗?@Moreno-要“真实”随机,我相信它需要基于一些随机的东西,这意味着一些“非编程”输入需要用作计算的一部分。我认为放射性物质的衰变可以利用吗?或者可能是供电水平的波动?因此,生成“真实”随机数与其说是软件问题,不如说是硬件问题。(但我肯定不是这方面的专家。也许读过。)
      mu = ((2 * f.Count(plus) * f.Count(minus)) / n) + 1
                               ^
                               Note the change here
      
      Sub WaldWolfowitz()
        Randomize
        Dim nRuns As Long ' counts the number of runs
        Dim x As Long ' a randomly picked value, 0 or 1
        Dim lastX As Long: lastX = -1 ' memorizes the last picked value to count runs
        Dim N(0 To 1) As Long ' array holds the number of picks of 0 and 1
      
        Dim i As Long, r As Double
        For i = 1 To 1000000
          r = Rnd
          x = IIf(r < 0.5, 0, 1)
          N(x) = N(x) + 1
          If x <> lastX Then nRuns = nRuns + 1
          lastX = x
        Next
      
        ' Distribution of the number of runs in the case
        ' the picks are independent (the null hypothesis)
        Dim mu As Double, variance As Double, sigma As Double, p As Double, z As Double
        mu = 1 + ((2 * N(0)) / (N(0) + N(1))) * N(1) ' rewrote it this way to avoid overflow
        variance = (mu - 1) * (mu - 2) / (N(0) + N(1) - 1)
        sigma = Sqr(variance)
      
        ' The p-test. We calculate the likelihood that the resulted number of runs
        ' be "that far" from mu. Notice in the calculation below:
        ' - We compute the absolute value of diff because it's a "two-tailed test"
        ' - We calculate the "tail" area under the normal curve from that point
        '   and we multiply it by two
        ' - The parameter "Cumlative:=True" for Norm_S_Dist to calculate the area under the normal curve
        z = Abs(nRuns - mu) / sigma
        p = 2 * (1 - WorksheetFunction.Norm_S_Dist(z, True))
      
        Debug.Print mu, sigma, nRuns, z, p
      End Sub