Об эффективности RND().

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Об эффективности RND().

Сообщение Mikle » 11.07.2005 (Пн) 9:08

Занимаюсь генерацией текстур. Алгоритм близок к шуму Перлина. Обратил внимание, что на текстурах просматривается не запланированный узор. Долго искал причину в алгоритме, а нашел в бейсиковской RND() :cry:
Попробовал тест - форму 640*480 попиксельно закрашивал цветом RND * &HFFFFFF. Результат налицо - RND выдает часто повторяющиеся рисунки. Это меня подвигло к разработке более "случайной" ф-ции. Вот результат:
Код: Выделить всё
Option Explicit
Dim Ri As Double

Function Rand() As Single
  Ri = 1.314 * Ri + 1.737
  If Ri > 983732.3456 Then Ri = Ri * 0.3141
  Rand = Ri - Int(Ri)
End Function

Sub RandInit(r As Single)
  Ri = r
End Sub

Rand - вместо RND
RandInit - вместо RANDOMIZE
Распределении гораздо ровнее, чем у RND и в Native Code работает в 3-4 раза быстрее.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 11.07.2005 (Пн) 9:35

А Randomize указывал перед RND()?
Lasciate ogni speranza, voi ch'entrate.

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 11.07.2005 (Пн) 10:16

alibek писал(а):А Randomize указывал перед RND()?

Подозреваю, что да...

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 11.07.2005 (Пн) 10:41

Я имею ввиду, перед каждым RND :)
Lasciate ogni speranza, voi ch'entrate.

uhm
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1597
Зарегистрирован: 02.12.2004 (Чт) 15:21

Сообщение uhm » 11.07.2005 (Пн) 12:30

Насчет равномерности - это ты загнул, у RND тоже равномерное распределение (сейчас специально попроверял :) ). Если работает быстрее - это здорово.

Зачем перед каждым RND ставить Randomize?

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 11.07.2005 (Пн) 12:52

alibek
Ставить перед каждым RND Randomize - теряется смысл RND. Первый раз я его, естественно, ставил.
uhm
Равномерность распределения у RND нормальная. Мне не нравится ПОВТОРЯЕМОСТЬ достаточно коротких последовательностей, что заметно на глаз.

uhm
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1597
Зарегистрирован: 02.12.2004 (Чт) 15:21

Сообщение uhm » 11.07.2005 (Пн) 13:14

Не понимаю, о какой "повторяемости" идет речь.
Может, ты приведешь пример кода?

_Мика_
Гуру
Гуру
 
Сообщения: 1459
Зарегистрирован: 24.10.2003 (Пт) 15:05
Откуда: г. Москва, м.Речной вокзал

Сообщение _Мика_ » 11.07.2005 (Пн) 13:21

Roman Koff писал(а):Раньше для модно было писать Randomize Timer


Randomize Timer писался, если я не ошибаюсь, в обычном Basic'е, а разве в VB есть такое? :roll:
-Папа, а правда, что форумы делают людей дибилами?
-гы гы гы, сынок, лол!

uhm
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1597
Зарегистрирован: 02.12.2004 (Чт) 15:21

Сообщение uhm » 11.07.2005 (Пн) 13:23

Randomize uses number to initialize the Rnd function's random-number generator, giving it a new seed value. If you omit number, the value returned by the system timer is used as the new seed value.


В смысле, если написать Randomize, то как раз с таймера Seed и возьмется.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 11.07.2005 (Пн) 13:30

Код: Выделить всё
Option Explicit
Dim Ri As Double

Function Rand() As Single
  Ri = 1.314 * Ri + 1.737
  If Ri > 983732.3456 Then Ri = Ri * 0.3141
  Rand = Ri - Int(Ri)
End Function

Sub RandInit(r As Single)
  Ri = r
End Sub

Private Sub Form_Load()
  Me.AutoRedraw = False
  Me.ScaleMode = vbPixels
End Sub

Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim X1 As Long, Y1 As Long
  If Button = 1 Then
    For Y1 = 0 To Me.ScaleHeight - 1
      For X1 = 0 To Me.ScaleWidth - 1
        Me.PSet (X1, Y1), Rnd * &HFFFFFF
      Next X1
    Next Y1
  Else
    For Y1 = 0 To Me.ScaleHeight - 1
      For X1 = 0 To Me.ScaleWidth - 1
        Me.PSet (X1, Y1), Rand * &HFFFFFF
      Next X1
    Next Y1
  End If
End Sub

Private Sub Form_Resize()
  Me.Caption = Me.ScaleWidth
End Sub

Вставь код в новый проект. Посмотри, как ведет себя RND (LeftClick) и Rand (RightClick) при разных размерах формы. Напр. при ScaleWidth=512.

uhm
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1597
Зарегистрирован: 02.12.2004 (Чт) 15:21

Сообщение uhm » 11.07.2005 (Пн) 13:35

:shock:

И вправду, я вижу некоторое подобие узора в RND...

Мда-а, задал ты мне задачку. Надо будет поразмышлять на досуге...

uhm
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1597
Зарегистрирован: 02.12.2004 (Чт) 15:21

Сообщение uhm » 11.07.2005 (Пн) 13:40

Хм-м-м-м-м...

Если изменять Width формы, узор может исчезнуть или проявиться. При width=5205 (scalewidth=5085) у меня в Rnd абсолютно четкие диагональные линии. Прикольно :o

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 11.07.2005 (Пн) 13:55

uhm
Если период повторяемости кратен ширине формы - полосы вертикальные. Если близко к этому - диагональные.
Каким образом вышло scalewidth=5085, ведь Me.ScaleMode = vbPixels?
Или ты изменил исходник? Просто запускай, меняй мышкой размеры формы, кликай - и смотри результат.

uhm
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1597
Зарегистрирован: 02.12.2004 (Чт) 15:21

Сообщение uhm » 11.07.2005 (Пн) 14:54

Не менял я исходник, просто ты же мне свою формочку не присылал, а scalemode в дизайн-моде по умолчанию в твипах. Вертикальные полосы мне получить пока не удалось, хотя хотелось :)

Вот уйду с работы, приду домой, и, если силы останутся, поэкспериментирую...

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 11.07.2005 (Пн) 16:33

uhm писал(а):Не менял я исходник, просто ты же мне свою формочку не присылал, а scalemode в дизайн-моде по умолчанию в твипах. Вертикальные полосы мне получить пока не удалось, хотя хотелось :)

Прочитай в его исходнике процедуру Form_Load, вторую строчку ;-)
Изображение

uhm
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1597
Зарегистрирован: 02.12.2004 (Чт) 15:21

Сообщение uhm » 11.07.2005 (Пн) 17:10

Да, вижу, и что? Еще раз говорю, что все изменения вносил в design-mode, где по умолчанию ScaleMode стоит "1 - Twip".

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 11.07.2005 (Пн) 20:57

uhm писал(а):Да, вижу, и что?

То, что после запуска формы всё равно станут пикселы. Хоть сантиметры в design-mode выставлены были, хоть что.
Изображение

uhm
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1597
Зарегистрирован: 02.12.2004 (Чт) 15:21

Сообщение uhm » 11.07.2005 (Пн) 21:58

Да это все понятно. Ты лучше скажи, почему при использовании RND возникает периодичность, да еще с таким небольшим периодом? :wink:

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 12.07.2005 (Вт) 7:56

Эта периодичность заложена в форме вычисления RND(). Правда странно, что она проявляется :) Я формулу не помню, в MSDN где-то была.
Lasciate ogni speranza, voi ch'entrate.

A.A.Z.
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3035
Зарегистрирован: 30.06.2003 (Пн) 13:38

Сообщение A.A.Z. » 12.07.2005 (Вт) 8:54

uhm писал(а)::shock:

И вправду, я вижу некоторое подобие узора в RND...

Мда-а, задал ты мне задачку. Надо будет поразмышлять на досуге...
http://bbs.vbstreets.ru/viewtopic.php?t=12716

uhm
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1597
Зарегистрирован: 02.12.2004 (Чт) 15:21

Сообщение uhm » 12.07.2005 (Вт) 12:55

Фракталы не при чем.

alibek, что он периодичен, я подозревал. Но не должен быть такой маленький период!

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Об эффективности RND().

Сообщение arthur2 » 16.03.2009 (Пн) 11:59

Прошу прощенья за некрофилию :oops: Зато здоровский топик подниму :)

Функция ништяк! Но интересно было бы понять, как именно ты подобрал параметры 1.314, 1.737 и пр.
Артур
 
   

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re:

Сообщение awl100Alex » 16.03.2009 (Пн) 12:48

alibek писал(а):Эта периодичность заложена в форме вычисления RND(). Правда странно, что она проявляется :) Я формулу не помню, в MSDN где-то была.


Правильно. Функция RND "генерирует" в VB равномерное рапределение случайных чисел в диапазоне от 0 до 1 - это псевдослучайные величины. На самом деле RND получает значения из таблицы так называемого математического ряда, который уже заранее создается машиной.
2^n - тоже дает бинарный ряд = 8,16,32,64,128,256 и т.д. У RND своя формула. А Randomize - все во лишь выполняет случайный вход в эту самую таблицу для функции RND. Случайность здесь мифическая.

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Об эффективности RND().

Сообщение awl100Alex » 16.03.2009 (Пн) 17:40

arthur2
Скорее всего подобрал он их экспериментальным путем. И, кстати, попробуй заменить эту функцию по правому клику...
Код: Выделить всё
Function Rand() As Single
  Ri = 1.1 * Ri + 1.1
  If Ri > 983732.3456 Then Ri = Ri * 0.0001 '0.3141
  Rand = Ri - Int(Ri)
End Function

Кликни несколько раз... увидишь, что это тоже псевдослучайнойсть, а вариант Ri = Ri * 0.3141 может так же проявится где-то случайным образом, как визуальный артефакт.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Об эффективности RND().

Сообщение Mikle » 16.03.2009 (Пн) 19:16

arthur2
Искал экспериментально.
awl100Alex
Ты бы еще вместо всех констант поставил "1" или "0" :lol:
Вообще у функции имеется "запас прочности" за счет того, что все считается в Double, а на выходе - Single.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Об эффективности RND().

Сообщение arthur2 » 16.03.2009 (Пн) 22:23

Mikle писал(а):Искал экспериментально.

Не, ну чем-то же всё-таки руководствовался? Не методом же перебора? Или чисто на интуиции?

Ведь получилось, вроде бы, куда лучше, чем rnd :)

А, кстати, какие ещё есть алгоритмы для генерации случайных чисел? Сам rnd(), интересно, как устроен?
Артур
 
   

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Об эффективности RND().

Сообщение awl100Alex » 16.03.2009 (Пн) 23:20

Mikle писал(а):Ты бы еще вместо всех констант поставил "1" или "0" :lol:

Я все во лишь уменьшил масштаб построений, который наглядно показал, что случайностей здесь нет! :)
Можно вернуть Ri = 1.314 * Ri + 1.737 и будет тоже самое.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Об эффективности RND().

Сообщение Mikle » 17.03.2009 (Вт) 11:23

awl100Alex
Я все во лишь уменьшил масштаб построений

Так о масштабе и речь, если он больше точности Single, то все в порядке.
arthur2
Не, ну чем-то же всё-таки руководствовался? Не методом же перебора? Или чисто на интуиции?

Долго объяснять, просто в школе математику хорошо понял. :roll:

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Об эффективности RND().

Сообщение arthur2 » 17.03.2009 (Вт) 12:24

Mikle писал(а):Долго объяснять, просто в школе математику хорошо понял.


Так ты долго не объясняй, раз так - просто ткни носом, в какую сторону посмотреть :)

Mikle писал(а):Так о масштабе и речь, если он больше точности Single, то все в порядке.

Это как-то и связано с принципом кода, да? Я пробовал менять разные цифры в константах, не меняя масштаба - шум получается без повторений, но не всегда равномерный.

А как оценить и проверить равномерность псевдослучайных цифр, не считая такого наглядного способа, как на глаз?
Артур
 
   

След.

Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: SemrushBot и гости: 2

    TopList