2013-05-01 2 views
1

Есть ли способ, чтобы я мог генерировать случайные числа от 0 до & HFFFFFFFF в 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

Проблема здесь является максимальное значение долго можно держать в 7fffffff или 2147483647 в десятичной форме Итак, как я должен это исправить? Даже если я использую один тип данных, он всегда возвращает отрицательный номер без неподписанных чисел.

В соответствии с MSDN Long типа

Long (длинное целое) переменные хранятся в виде подписанного 32-бит (4 байта) чисел в диапазоне от стоимости -2147483648 до 2147483647. Характер символа типа для Long - амперсанд (&).

Но значение 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

Просто используйте правильный PRNG и прочитайте 4 байта. – CodesInChaos

+1

Обратите внимание, что этот метод вызова машинного кода ** небезопасен **! Он не работает в современных системах Windows с [защитой выполнения данных] (http://en.wikipedia.org/wiki/Data_Execution_Prevention), что делает его хрупким или внезапным сбоем в современных системах.Вы * должны * заранее отмечать такую ​​память, как исполняемую, с помощью функции WinAPI VirtualProtect. [Вот пример кода] (http://www.activevb.de/tipps/vb6tipps/tipp0715.html) - хотя и с немецкими комментариями. –

+0

Да, почти забыл об этом, спасибо за голову. –

ответ

1

&HFFFFFFFF - представляет собой 32-разрядное целое число, а значение &HFFFFFFFF разливается целое и становится -1 Следовательно, при вызове функции RandomNumberLong, вы передаете от 0 до LowerBound и -1 к UpperBound

Чтобы исправить это на Vb.NET, используйте &HFFFFFFFFL или &HFFFFFFFF&, чтобы указать литерал длинного типа. Я не уверен, как быстро исправить это в VB6, как в VB.NET, из приведенного выше примера. Думаю, вам нужно будет написать свою собственную функцию, чтобы преобразовать большие числа HEX, чтобы удвоить и передать число вместо HEX.

EDIT: Я не думаю, что VB6 позволяет конвертировать &HFFFFFFFF ни к чему, но основание 16, которое переполняет и приводит к -1:

EDIT 2: Вы можете конвертировать несколько номеров Hex в другой тип данных по добавляя & до конца:

&HFFFF = -1 
&HFFFF& = 65535 

Тем не менее, там, кажется, предел числа Hex в VB6 (? основание 16 только), потому что:

VB.NET: 
&HFFFFFFFF&=4294967295 

VB6: 
&HFFFFFFFF&=-1 

MSDN: Type Characters (Visual Basic)

Компилятор обычно конструирует целое число буквального быть в десятичной системе (основание 10) системы счисления. Вы можете заставить целочисленный литерал быть шестнадцатеричным (базовый 16) с префиксом & H, и вы можете заставить его быть восьмеричным (база 8) с префиксом & O. Цифры, которые следуют за префиксом, должны соответствовать порядковым номерам.

+0

Спасибо, Джордж за это. Вместо этого я использовал инструкцию RDTSC для генерации случайного длинного числа. Вы можете видеть это в вопросе. –

0

Rnd только даст вам 24 бит случайности, поскольку он возвращает Single.

RandomNumberLong = Clng(&HFFFF * Rnd()) + (Clng(&HFFFF * Rnd()) * &H10000) 

будет строить 32-битное значение из двух 16-разрядных случайных целых чисел.

ОБНОВЛЕНИЕ - ну, это не так, потому что, как указывает Hrqls, &HFFFF - -1 в VB. Вместо этого:

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

Кажется, не отвечает на вопрос. Прямо сейчас, он получает 0 бит случайности. : P Эта ошибка почти наверняка не имеет никакого отношения к точности «Single». (С учетом сказанного, однако, это по-прежнему хорошая информация для более поздних, когда вещь действительно способна производить номера.) – cHao

+0

Я протестировал вашу функцию и возвращает один из следующих FFFEFFFF или FFFF0000 или FFFFFFFF или 0. –

+0

'Single '32-бит в VB6. –

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 
1

Проблема заключается в том, что VB6 преобразует любое шестнадцатеричное число, которое выходит из только из «F» до -1

Это сделает вашу функцию, чтобы использовать -1 в качестве UpperBound, и заставляет его вернуться 0

разделяя 8 цифр Int o 2 переменные с 4 цифрами, у вас все еще есть та же проблема, что и 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 

Запуск проекта выше, и нажмите кнопку команды и просмотреть значения в заголовке формы.

+0

«Проблема в том, что VB6 преобразует любое шестнадцатеричное число, которое выходит из« F »в -1» - не совсем точно. '& HF = 15',' & HFF = 255', '& HFFF = 4095',' & HFFFF = -1', '& HFFFFF = 1048575',' & HFFFFFF = 16777215', '& HFFFFFFF = 268435455',' & HFFFFFFFF = -1' и все, что выходит за рамки этого, приводит к ошибке компиляции. – George

+1

Кроме того, '& HFFFF & = 65535'. Поэтому только после больших чисел HEX, таких как '& HFFFFFFFF', мы начинаем видеть переполнение. Все до этого выглядит хорошо. – George

+0

Согласен, я немного упростил ответ. Думаю, я должен был сказать, что наборы из 4 байтов. Я не думал добавлять и заканчивать, потому что он не будет работать с 8 байтами, приятное дополнение! – Hrqls

Смежные вопросы