excel - 为什么我的随机数在 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 中是否有任何设置阻止我的代码正常运行?
任何解释和解决方案将不胜感激!:)
解决方案
您描述的行为是一个错误。
首先,如果我们替换行:
Randomize i
和:
Randomize 0
我们可以看到,在 Windows 上,我们得到与在 Mac 上完全相同的重复值:
这立即向我暗示只能有两种可能的解释:
- 可能算法不一样
- 存在问题,并且 的值
i
未正确传递/读取。
为了找到一个规则,我使用了一种单独的方法(蛮力 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 上得到相同的结果。
我在那些神奇的数字中找不到清晰的模式,所以我放弃了算法不同的说法。这让我找到了问题/错误。
经过反复试验,我发现如果我们将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
、声明了所有变量并缩进了代码。
推荐阅读
- node.js - fetch api 无法访问 nodejs + express url
- wordpress - 使用wordpress建立一个商业网站
- nosql - 不进行大量扫描时的表扫描与 GSI
- javascript - 无法将我的 Javascript 对象转换为参数字符串
- typescript - 如何使用 fetch-mock 获取请求的正文
- asp.net - 从 iis 获取站点状态
- vue.js - 如何更改 Vuetify Datatable 中选定行的背景颜色?
- javascript - 如何在容器流体中使用引导 4 容器,如何将文本始终留在容器内
- php - 如何使用json进行两个表内连接
- angular - 迁移到 Angular 8 时的依赖问题