有没有什么方法可以在Visual Basic 6.0中生成0到& HFFFFFFFF的随机数?
我正在使用以下功能
Function RandomNumberLong(Lowerbound As Long, Upperbound As Long) As Long
RandomNumberLong = Clng((Upperbound - Lowerbound + 1) * Rnd + Lowerbound)
End Function
如果我使用
x = RandomNumberLong(0,&HFFFFFFFF)
总是返回0
这里的问题是long可以保持的最大值是7FFFFFFF或2147483647(十进制) 那我该怎么办呢?即使我使用单一数据类型,它也总是返回负数而没有无符号数。
根据MSDN Long类型
长(长整数)变量存储为带符号的32位(4字节) 数字范围从-2,147,483,648到2,147,483,647。 Long的type-declaration字符是&符号(&)。
但是FFFFFFFF的值等于-1或4294967294溢出。
我觉得我对此很困惑。
编辑:
由于这似乎有点复杂,我编写了一个小的Shell代码来使用RDTSC指令代替生成一个随机的长数字,包括烧结和无符号。
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Option Explicit
Private Sub Form_Load()
Dim x(1 To 10) As Byte, VAL As Long
CopyMemory x(1), &H60, 1 'PUSHAD
CopyMemory x(2), &H310F, 2 'RDTSC EAX holds a random value
CopyMemory x(4), &HA3, 1 'MOV EAX
CopyMemory x(5), VarPtr(VAL), 4 'Pointer of variable // MOV DWORD [VAL],EAX
CopyMemory x(9), &H61, 1 'POPAD
CopyMemory x(10), &HC3, 1 'RET
CallWindowProc VarPtr(x(1)), 0, 0, 0, 0 'Call the shellcode
MsgBox VAL
End Sub
答案 0 :(得分:1)
&HFFFFFFFF
- 表示32位有符号整数,&HFFFFFFFF
的值溢出整数并变为-1
因此,当您调用RandomNumberLong
函数时,您将0传递给Lowerbound而-1传递给Upperbound
要在Vb.NET中修复此问题,请使用&HFFFFFFFFL
或&HFFFFFFFF&
来指示Long类型文字。我不确定如何在VB6中快速解决这个问题,如上例中的VB.NET。我想你需要编写自己的函数来将大的十六进制数转换为double并传递数字而不是HEX。
编辑:
我不认为VB6允许你将&HFFFFFFFF
转换为除16之外的任何东西,它会溢出并导致-1:
编辑2:
您可以通过在末尾添加&
将一些十六进制数转换为其他数据类型:
&HFFFF = -1
&HFFFF& = 65535
但是,VB6中的十六进制数似乎有限制(仅限基数16?),因为:
VB.NET:
&HFFFFFFFF&=4294967295
VB6:
&HFFFFFFFF&=-1
MSDN: Type Characters (Visual Basic)
编译器通常将整数文字构造为十进制(基数为10)的数字系统。您可以使用& H前缀强制整数文字为十六进制(基数为16),并且可以使用& O前缀强制它为八进制(基数为8)。前缀后面的数字必须适合数字系统。
答案 1 :(得分:1)
事实是VB6 Long
是32位签名的整数数据类型。因此,它无法存储&HFFFFFFFF
(MSDN)。但是(1)无论如何你似乎没有使用Long
,而且(2)你没有解释你的用例是什么,以及它是否真的只能在正范围内工作。
可以使用以下函数从整个Long
数据类型(即从Long
到-&H80000000
)生成随机&H7FFFFFFF
值:
Function RandomNumberLong() As Long
RandomNumberLong = &H7FFFFFFF * Rnd() + (-1 - &H7FFFFFFF) * Rnd()
End Function
答案 2 :(得分:1)
问题是VB6将从“F”退出的任何十六进制数转换为-1
这将使您的函数使用-1作为其上限,并使其返回0
通过将8位数字分成4个数字的2个变量,你仍然会遇到同样的问题,因为VB6仍会将& HFFFF转换为-1,这将使你的函数再次返回0。
解决方案是在转换之前将& H10000添加到4位数变量,并在转换完成后减去Val(“& H10000”)。
之后,您可以使用这两个值来获得2个随机数,并将它们组合成1个随机的8位十六进制数。
下面是一个显示我的意思的测试项目:
'1 form with:
' 1 command button: name=Command1
Option Explicit
Private Sub Command1_Click()
Dim strX As String
Dim lngX As Long
strX = RndHex("FFFFFFFF")
lngX = Val("&H" & strX)
Caption = strX & " = " & CStr(Hex$(lngX)) & " = " & CStr(lngX)
End Sub
Function RndHex(strMax As String) As String
Dim strMax1 As String, strMax2 As String
Dim lngMax1 As Long, lngMax2 As Long
Dim lngVal1 As Long, lngVal2 As Long
Dim strVal1 As String, strVal2 As String
'make sure max is 8 digits
strMax1 = Right$("00000000" & strMax, 8)
'split max in 2 parts
strMax2 = Right$(strMax1, 4)
strMax1 = Left$(strMax1, 4)
'convert max values from string to values
lngMax1 = Val("&H1" & strMax1) - Val("&H10000")
lngMax2 = Val("&H1" & strMax2) - Val("&H10000")
'calculate separate random values
lngVal1 = CLng(lngMax1 + 1) * Rnd
lngVal2 = CLng(lngMax2 + 1) * Rnd
'convert values to 4 digit hex strings
strVal1 = Right$("0000" & Hex$(lngVal1), 4)
strVal2 = Right$("0000" & Hex$(lngVal2), 4)
'combine 2 random values and return the result as an 8 digit hex string
RndHex = strVal1 & strVal2
End Function
Private Sub Form_Load()
'seed random generator with system timer
Randomize
End Sub
运行上面的项目并单击命令按钮,然后查看表单标题中的值。
答案 3 :(得分:0)
Rnd
只会提供24位随机性,因为它会返回Single
。
RandomNumberLong = Clng(&HFFFF * Rnd()) + (Clng(&HFFFF * Rnd()) * &H10000)
将从两个16位随机整数构造一个32位值。
更新 - 好吧,它不会,因为正如Hrqls指出的那样,&HFFFF
在VB中是-1
。代替:
RandomNumberLong = Clng(65535 * Rnd()) + (Clng(65535 * Rnd()) * 65536)