
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.198] |
![]() |
|
Сообщ.
#1
,
|
|
|
Нашёл в инете инфу про параметры КГ (k(i)=(a*k(i-1) + c) mod m) для RND VB6:
a=1140671485 c=12820163 m=2^24 проверяю: ![]() ![]() Dim lM As Long, Seed As Single, i As Long lM = 2 ^ 24 Seed = 1 Randomize Seed Debug.Print Rnd Debug.Print ((1140671485 * Seed + 12820163) And (lM - 1)) / lM не сходится... может, при преобразовании в вещественное деление происходит не на 2^24, а на другое число? |
Сообщ.
#2
,
|
|
|
http://support.microsoft.com/kb/231847
В VB6 нет беззнаковой арифметики, можно через API функций вычислить. |
Сообщ.
#3
,
|
|
|
не вижу тут влияние знака, по крайней мере в данном примере...
|
Сообщ.
#4
,
|
|
|
BlackSun, да действительно алгоритм там неверный. Поверхностный анализ дал такой алгоритм (без проверок):
![]() ![]() Option Explicit Private Type INT64 l As Long h As Long End Type Private Type CUR v As Currency End Type Private Sub Form_Load() Dim Seed As Long, i As Long Seed = 0 Randomize Seed For i = 0 To 10 Debug.Print Rnd Debug.Print MyRnd Next End Sub Private Function MyRnd() As Single Dim c As CUR Static i As INT64 c.v = 429101.0243@ - (CCur(i.l / 10000) * 179203@) LSet i = c: i.l = (i.l And &HFFFFFF) MyRnd = i.l / &H1000000 End Function |
Сообщ.
#5
,
|
|
|
объясни плиз, что ты намудрил, что от этого изменилось?
Добавлено оказывается, при Seed=0 результат аналогичный, а вот при Seed>0 уже не тот... Значит, Seed используется не так как я представляю в коде, а как-то иначе? |
Сообщ.
#6
,
|
|
|
Цитата BlackSun @ объясни плиз, что ты намудрил, что от этого изменилось? Ты код смотрел вообще? Запускал? Не видишь что изменилось? Это тот же конгруэнтный метод, только коэффициенты другие, но они по прежнему должны быть беззнаковыми. Цитата NewVal = 0xFFC39EC3 - (OldVal * 0x2BC03) Добавлено Цитата BlackSun @ оказывается, при Seed=0 результат аналогичный, а вот при Seed>0 уже не тот... Значит, Seed используется не так как я представляю в коде, а как-то иначе? Код смотри, Seed - начальное значение генератора, у меня оно всегда 0 (смотри первый вызов функции чему равно i.l?), можешь делать какое хочешь. |
Сообщ.
#7
,
|
|
|
так у меня знак не имеет значения, 1140671485 вмещается в Long.
Добавлено вернее знаковый бит не используется. |
Сообщ.
#8
,
|
|
|
Цитата BlackSun @ так у меня знак не имеет значения, 1140671485 вмещается в Long. Причем здесь 1140671485? Метод в статье - неверный, я же написал. Смотри мою формулу, которую я привел в 6-м посте. Представь у тебя OldVal будет равно к примеру &HFFFFFF& - что будет? Насчет инициализации генератора, там тоже не все так просто. Переданное число конвертируется в 64-разрядное с плавающей точкой, из него берется 4 верхних байта и перетасовываются. Вот небольшой пример: ![]() ![]() Option Explicit Private Type INT64 l As Long h As Long End Type Private Type CUR v As Currency End Type Private Type DBL d As Double End Type Dim oldVal As INT64 Private Sub Form_Load() Dim Seed As Long, i As Long InitMyRnd Debug.Print "Pass 1:" For i = 0 To 10 Debug.Print Rnd Debug.Print MyRnd Next Randomize 500 MyRandomize 500 Debug.Print "Pass 2:" For i = 0 To 10 Debug.Print Rnd Debug.Print MyRnd Next End Sub Private Function MyRnd() As Single Dim c As CUR c.v = 429101.0243@ - (CCur(oldVal.l / 10000) * 179203@) LSet oldVal = c: oldVal.l = (oldVal.l And &HFFFFFF) MyRnd = oldVal.l / &H1000000 End Function Private Sub MyRandomize(ByVal Seed As Long) Dim r As DBL, l As INT64 r.d = CDbl(Seed) LSet l = r oldVal.l = ((l.h \ &H100) And &HFFFF00) Xor ((l.h And &HFFFF&) * &H100) Or (oldVal.l And &HFF0000FF) End Sub Private Sub InitMyRnd() oldVal.l = 327680 End Sub |