为什么我的随机数在 Excel 中没有相应变化?
Why are my random numbers not changing accordingly in Excel?
我下面有一些代码可以在 Excel 中生成一些随机数:
Sub Macro1()
Dim RA1 As Variant
ReDim RA1(1 To 5)
For i = 1 To 5
Rnd (-1)
Randomize i
For j = 1 To 5
RA1(j) = Rnd
Next j
With Sheets("Sheet1")
.Range(Cells(i, 1), Cells(i, 5)).Value = RA1
End With
Next i
End Sub
这段代码基本上生成了 5 行 5 个随机数,但它并不是 运行 应有的样子。当我在我的 iMac(2021)上 运行 这段代码时,每行中的随机数完全相同。但是,这段代码应该生成 5 行不同的随机数。
这里是事情变得更加奇怪的地方。当我在我的 Windows 笔记本电脑上 运行 这段代码时,输出是我想要的——也就是说,我确实得到了 5 行不同的随机数。我已经和我的教授谈过这个,他也在他的 Windows 电脑上试过了,得到了 5 行不同的随机数。
总而言之,我们基本上不知道为什么我的 iMac 无法 运行 这段代码。有没有人猜测为什么这里存在这种差异?例如,我的 iMac Excel 中是否有任何设置阻止我的代码正确 运行ning?
任何解释和解决方案将不胜感激! :)
如果您阅读 Randomize statement 的手册,您可以找到以下内容:
To repeat sequences of random numbers, call Rnd with a negative argument immediately before using Randomize with a numeric argument. Using Randomize with the same value for number does not repeat the previous sequence.
所以我强烈建议删除 Rnd (-1)
,这会使它重复随机数序列。
也尝试从 Randomize i
中删除种子并仅使用 Randomize
以便计算机将系统计时器作为种子(以获得更好的随机数)。
// 根据评论编辑
如果您每次都需要相同的数字但每次都需要不同的数字rows/columns那么您可能需要在第一次循环之前进行初始化。
Rnd -1
Randomize 1 'if you don't need the same seed everytime use Randomize without number
For i = 1 To 5
您描述的行为是一个错误。
首先,如果我们替换行:
Randomize i
与:
Randomize 0
我们可以看到在 Windows 上得到的重复值与在 Mac 上得到的重复值完全相同:
这立即让我想到只有两种可能的解释:
- 可能是算法不同
- 出现问题,
i
的值不正确 passed/read。
为了找规律,我用了单独的方法(暴力破解i/x),找到了下面的幻数。同样,如果我们替换行:
Randomize i
与:
#If Mac Then
Dim arr() As Variant: arr = Array(26489, 63707, 185603, 15365, 92513)
Randomize i / arr(i - 1)
#Else
Randomize i
#End If
我们在 Windows 和 Mac 上得到相同的结果。
我在那些幻数中找不到明确的模式,所以我放弃了算法不同。这让我找到了 issue/bug.
经过反复试验,我发现如果我们将 Double
数据类型传递给 Randomize
方法,它不会读取完整的 8 个字节,而只会读取前 4 个字节。这就是除以那些神奇数字的原因,因为(这些除法的)结果数字使用前 4 个字节(包括指数位)而不是 8 个完整字节。
解决方法是将双精度值(向左)偏移 4 个字节。这是适用于 Windows 和 Mac 的最终代码:
Option Explicit
#If Mac Then
#If VBA7 Then
Public Declare PtrSafe Function CopyMemory Lib "/usr/lib/libc.dylib" Alias "memmove" (Destination As Any, Source As Any, ByVal Length As LongPtr) As LongPtr
#Else
Public Declare Function CopyMemory Lib "/usr/lib/libc.dylib" Alias "memmove" (Destination As Any, Source As Any, ByVal Length As Long) As Long
#End If
#End If
Sub Macro1()
Dim i As Long
Dim j As Long
Dim RA1 As Variant
ReDim RA1(1 To 5)
For i = 1 To 5
Rnd (-1)
#If Mac Then
Dim d As Double
d = CDbl(i)
CopyMemory d, ByVal VarPtr(d) + 4, 4 'Read the last 4 double bytes into the first 4
Randomize d
#Else
Randomize i
#End If
For j = 1 To 5
RA1(j) = Rnd
Next j
With Sheets("Sheet1")
.Range(Cells(i, 1), Cells(i, 5)).Value = RA1
End With
Next i
End Sub
您会注意到我还添加了 Option Explicit
、声明了所有变量并缩进了代码。
我下面有一些代码可以在 Excel 中生成一些随机数:
Sub Macro1()
Dim RA1 As Variant
ReDim RA1(1 To 5)
For i = 1 To 5
Rnd (-1)
Randomize i
For j = 1 To 5
RA1(j) = Rnd
Next j
With Sheets("Sheet1")
.Range(Cells(i, 1), Cells(i, 5)).Value = RA1
End With
Next i
End Sub
这段代码基本上生成了 5 行 5 个随机数,但它并不是 运行 应有的样子。当我在我的 iMac(2021)上 运行 这段代码时,每行中的随机数完全相同。但是,这段代码应该生成 5 行不同的随机数。
这里是事情变得更加奇怪的地方。当我在我的 Windows 笔记本电脑上 运行 这段代码时,输出是我想要的——也就是说,我确实得到了 5 行不同的随机数。我已经和我的教授谈过这个,他也在他的 Windows 电脑上试过了,得到了 5 行不同的随机数。
总而言之,我们基本上不知道为什么我的 iMac 无法 运行 这段代码。有没有人猜测为什么这里存在这种差异?例如,我的 iMac Excel 中是否有任何设置阻止我的代码正确 运行ning?
任何解释和解决方案将不胜感激! :)
如果您阅读 Randomize statement 的手册,您可以找到以下内容:
To repeat sequences of random numbers, call Rnd with a negative argument immediately before using Randomize with a numeric argument. Using Randomize with the same value for number does not repeat the previous sequence.
所以我强烈建议删除 Rnd (-1)
,这会使它重复随机数序列。
也尝试从 Randomize i
中删除种子并仅使用 Randomize
以便计算机将系统计时器作为种子(以获得更好的随机数)。
// 根据评论编辑
如果您每次都需要相同的数字但每次都需要不同的数字rows/columns那么您可能需要在第一次循环之前进行初始化。
Rnd -1
Randomize 1 'if you don't need the same seed everytime use Randomize without number
For i = 1 To 5
您描述的行为是一个错误。
首先,如果我们替换行:
Randomize i
与:
Randomize 0
我们可以看到在 Windows 上得到的重复值与在 Mac 上得到的重复值完全相同:
这立即让我想到只有两种可能的解释:
- 可能是算法不同
- 出现问题,
i
的值不正确 passed/read。
为了找规律,我用了单独的方法(暴力破解i/x),找到了下面的幻数。同样,如果我们替换行:
Randomize i
与:
#If Mac Then
Dim arr() As Variant: arr = Array(26489, 63707, 185603, 15365, 92513)
Randomize i / arr(i - 1)
#Else
Randomize i
#End If
我们在 Windows 和 Mac 上得到相同的结果。
我在那些幻数中找不到明确的模式,所以我放弃了算法不同。这让我找到了 issue/bug.
经过反复试验,我发现如果我们将 Double
数据类型传递给 Randomize
方法,它不会读取完整的 8 个字节,而只会读取前 4 个字节。这就是除以那些神奇数字的原因,因为(这些除法的)结果数字使用前 4 个字节(包括指数位)而不是 8 个完整字节。
解决方法是将双精度值(向左)偏移 4 个字节。这是适用于 Windows 和 Mac 的最终代码:
Option Explicit
#If Mac Then
#If VBA7 Then
Public Declare PtrSafe Function CopyMemory Lib "/usr/lib/libc.dylib" Alias "memmove" (Destination As Any, Source As Any, ByVal Length As LongPtr) As LongPtr
#Else
Public Declare Function CopyMemory Lib "/usr/lib/libc.dylib" Alias "memmove" (Destination As Any, Source As Any, ByVal Length As Long) As Long
#End If
#End If
Sub Macro1()
Dim i As Long
Dim j As Long
Dim RA1 As Variant
ReDim RA1(1 To 5)
For i = 1 To 5
Rnd (-1)
#If Mac Then
Dim d As Double
d = CDbl(i)
CopyMemory d, ByVal VarPtr(d) + 4, 4 'Read the last 4 double bytes into the first 4
Randomize d
#Else
Randomize i
#End If
For j = 1 To 5
RA1(j) = Rnd
Next j
With Sheets("Sheet1")
.Range(Cells(i, 1), Cells(i, 5)).Value = RA1
End With
Next i
End Sub
您会注意到我还添加了 Option Explicit
、声明了所有变量并缩进了代码。