Random 从0到&;的随机数;hffffff

Random 从0到&;的随机数;hffffff,random,vb6,Random,Vb6,有什么方法可以在VisualBasic6.0中生成从0到&hffffff的随机数 我正在使用以下函数 Function RandomNumberLong(Lowerbound As Long, Upperbound As Long) As Long RandomNumberLong = Clng((Upperbound - Lowerbound + 1) * Rnd + Lowerbound) End Function 如果我使用 x = RandomNumberLong(0,&

有什么方法可以在VisualBasic6.0中生成从0到&hffffff的随机数

我正在使用以下函数

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 can hold的最大值是7FFFFFFF或2147483647(十进制) 那么我该怎么解决这个问题呢?即使我使用单一的数据类型,它也总是返回负数,没有无符号数字

根据MSDN长型

长(长整数)变量存储为有符号32位(4字节) 数值范围从-2147483648到2147483647。 Long的类型声明字符是和(&)

但FFFFFF的值等于-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

Rnd
只会给您24位随机性,因为它返回一个
单数

 RandomNumberLong = Clng(&HFFFF * Rnd()) + (Clng(&HFFFF * Rnd()) * &H10000)
将从两个16位随机整数构造一个32位值

更新-嗯,它不会,因为正如Hrqls指出的,
&HFFFF
在VB中是
-1
。相反:

 RandomNumberLong = Clng(65535 * Rnd()) + (Clng(65535 * Rnd()) * 65536)

&HFFFFFFFF
-表示32位有符号整数,
&hffffff
的值溢出该整数并变为
-1
因此,当调用
RandomNumberLong
函数时,将0传递给下限,将-1传递给上限

要在Vb.NET中解决此问题,请使用
&hffffffl
&HFFFFFFFF&
指示长类型文字。我不知道如何在VB6中像在上面的例子中的VB.NET中那样快速地解决这个问题。我想您需要编写自己的函数来将大十六进制数转换为双精度数,并传递数字而不是十六进制数

编辑: 我认为VB6不允许您将
&HFFFFFFFF
转换为除base 16之外的任何东西,它会溢出并导致-1:

编辑2: 通过在末尾添加
&
,可以将一些十六进制数转换为其他数据类型:

&HFFFF = -1
&HFFFF& = 65535
不过,VB6中的十六进制数似乎有一个限制(仅限基数16?),因为:

VB.NET:
&HFFFFFFFF&=4294967295

VB6:
&HFFFFFFFF&=-1

编译器通常将整数文本构造为十进制(以10为基数)数字系统。您可以强制整数文本为带&H前缀的十六进制(以16为基数),也可以强制它为带&O前缀的八进制(以8为基数)。前缀后面的数字必须适合数字系统


事实上,VB6
Long
是32位有符号整数数据类型。因此,它无法存储
&HFFFFFFFF
()。但是(1)不管怎样,您似乎可以使用
Long
,并且(2)您没有解释您的用例是什么,以及是否只在积极的范围内工作真的那么重要

可以使用以下函数从整个
Long
数据类型范围(即从
-&h8000000
&H7FFFFFFF
)生成随机
Long
值:


问题是VB6将任何仅从“F”中退出的十六进制数转换为-1

这将使函数使用-1作为上限,并使其返回0

通过将8位数字拆分为2个4位变量,您仍然会遇到与VB6相同的问题,因为VB6仍然会将&HFFFF转换为-1,这将使您的函数再次返回0

一种解决方案是在转换前将&H10000添加到4位变量中,并在转换完成后减去Val(&H10000”)

之后,您可以使用这2个值获得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

运行上面的项目,单击命令按钮并查看表单标题中的值。

只需使用正确的PRNG并读取4个字节。请注意,这种调用机器代码的方法是不安全的!它将在带有的现代Windows系统上失败,使其在现代系统上变得脆弱或彻底崩溃。必须事先使用
VirtualProtect
WinAPI函数将该内存标记为可执行虽然有德国的评论。是的,差点忘了,谢谢你的提醒。似乎没有回答这个问题。现在,他得到了0位随机性P几乎可以肯定,这个错误与单个
的精度无关。(尽管如此,这对于以后实际能够生成数字的时候来说仍然是一个很好的信息。)我测试了您的函数,它返回以下FFFEFFFF或FFFF0000或FFFFFF或0中的一个。
Single
在VB6中是32位的。是的,Single是32位,但Rnd返回的值介于0和1之间,因此符号位和7个指数位不会增加任何随机性。+1用于将8个数字拆分为2x 4个数字。。。但问题仍然存在,因为vb仍然将&HFFFF转换为-1。。。请看下面我的答案,它围绕着这个问题工作。谢谢你,乔治。我使用RDTSC指令来生成一个随机长数。你可以在问题中看到它。”问题是VB6将任何只存在于“F”之外的十六进制数转换为-1,这并不完全准确
&HFFF=15
&HFFF=255
&HFFF=4095
&HFFFF=-1
&HFFFFF=1048575
&HFFFFF=16777215
&HFFFFF=268435455
&HFFFFF=-1
,以及任何超出此范围的内容都会导致编译错误。此外,
&HFFFF&=65535
。因此,只有在像
&HFFFFFFFF
这样的大十六进制数之后,我们才会开始看到溢出。之前的一切看起来都不错。我同意,我把答案简化了一点。我想我应该说是4个字节的集合。我没有想到在末尾添加a&因为它不能处理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