Что нового

[Random] Размышления на тему получение нормально распределенных чисел

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Yashied [?]
А вот интересно, как зделать ГСЧ с Гауссовским распределением?
Код:
$Pi = 3.14159265358979; ну вы поняли что это
$a = -10; левая граница
$b = 10; правая граница
$sigma = 2; дисперсия
$mu = 3; мат. ожидание
$uniform = random($a, $b); равномерно распределенное число
$gaussian = (1/($sigma*Sqrt(2*$Pi)))*Exp(-($uniform - $mu)^2/(2*$sigma^2)); нормально распределенное число

по идее так
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 712
Re: [Математика] Рандомный Random

OffTopic:
Ммм... Немного странный результат... Мат. ожидание куда-то убежало и причем здесь Sqrt(2*$Pi) ?

:shok:

Код:
#Include <GDIPlus.au3>
#Include <GUIConstantsEx.au3>
#Include <Math.au3>
#Include <WinAPI.au3>

Global Const $Pi = 3.14159265358979

Dim $aPoints[100][2] = [[0.0, 0]]

For $i = 1 To 99
	$aPoints[$i][0] = $aPoints[$i - 1][0] + 0.01
	$aPoints[$i][1] = 0
Next
For $i = 1 To 100000
;	$Val = Random(0, 1)
    $Val = _GRandom(0, 1)
    For $j = 0 To UBound($aPoints) - 1
        If ($Val >= $aPoints[$j][0]) And ($Val <= $aPoints[$j][0] + 0.01) Then
            $aPoints[$j][1] +=1
            ExitLoop
        EndIf
    Next
Next
$Max = 0
For $i = 0 To UBound($aPoints) - 1
	ConsoleWrite(StringFormat('%.2f', $aPoints[$i][0]) & '   ' & $aPoints[$i][1] & @CR)
	If $Max < $aPoints[$i][1] Then
		$Max = $aPoints[$i][1]
	EndIf
Next
For $i = 0 To UBound($aPoints) - 1
	$aPoints[$i][1] /= $Max
Next

_ViewGraph($aPoints)

Func _GRandom($Min, $Max)

	Local $D = 2

	Return (1 / ($D * Sqrt(2 * $Pi))) * Exp(-(Random($Min, $Max) - ($Min + $Max) / 2) ^ 2 / (2 * $D ^ 2))
EndFunc   ;==>_GRandom

Func _ViewGraph($aPoints)

	Local $hForm, $Pic, $hPic
	Local $Scale, $Xi, $Yi, $Xp, $Yp, $XOffset, $YOffset, $Xmin = $aPoints[0][0], $Ymin = $aPoints[0][1], $Xmax = $Xmin, $Ymax = $Ymin
	Local $hBitmap, $hObj, $hGraphic, $hImage, $hBrush, $hPen

	For $i = 1 To UBound($aPoints) - 1
		If $aPoints[$i][0] < $Xmin Then
			$Xmin = $aPoints[$i][0]
		Else
			If $aPoints[$i][0] > $Xmax Then
				$Xmax = $aPoints[$i][0]
			EndIf
		EndIf
		If $aPoints[$i][1] < $Ymin Then
			$Ymin = $aPoints[$i][1]
		Else
			If $aPoints[$i][1] > $Ymax Then
				$Ymax = $aPoints[$i][1]
			EndIf
		EndIf
	Next

	$Scale = 560 / _Max($Xmax - $Xmin, $Ymax - $Ymin)
	$XOffset = Floor(($Xmin + $Xmax) * $Scale / 2)
	$YOffset = Floor(($Ymin + $Ymax) * $Scale / 2)

	_GDIPlus_Startup()
    $hBitmap = _WinAPI_CreateBitmap(601, 601, 1, 32)
    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
	_WinAPI_DeleteObject($hBitmap)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)
	$hBrush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF)
	$hPen = _GDIPlus_PenCreate(0xFFFF0000)
	_GDIPlus_GraphicsFillRect($hGraphic, 0, 0, 601, 601, $hBrush)
	_GDIPlus_GraphicsSetSmoothingMode($hGraphic, 2)
	If Abs($XOffset) <= 300 Then
		_GDIPlus_GraphicsDrawLine($hGraphic, 300 - $XOffset, 0, 300 - $XOffset, 601, $hPen)
	EndIf
	If Abs($YOffset) <= 300 Then
		_GDIPlus_GraphicsDrawLine($hGraphic, 0, 300 + $YOffset, 601, 300 + $YOffset, $hPen)
	EndIf
	_GDIPlus_PenDispose($hPen)
	$hPen = _GDIPlus_PenCreate(0xFF000000)
	For $i = 0 To UBound($aPoints) - 1
		$Xi = 300 - $XOffset + $Scale * $aPoints[$i][0]
		$Yi = 300 + $YOffset - $Scale * $aPoints[$i][1]
		If $i Then
			_GDIPlus_GraphicsDrawLine($hGraphic, $Xp, $Yp, $Xi, $Yi, $hPen)
		EndIf
		$Xp = $Xi
		$Yp = $Yi
	Next
    $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
	_GDIPlus_GraphicsDispose($hGraphic)
	_GDIPlus_ImageDispose($hImage)
	_GDIPlus_BrushDispose($hBrush)
	_GDIPlus_PenDispose($hPen)
	_GDIPlus_Shutdown()

	$hForm = GUICreate('My Graph', 601, 601)
	$Pic = GUICtrlCreatePic('', 0, 0, 601, 601)
	$hPic = GUICtrlGetHandle(-1)

	_WinAPI_DeleteObject(_SendMessage($hPic, 0x0172, 0, $hBitmap))
	$hObj = _SendMessage($hPic, 0x0173)
	If $hObj <> $hBitmap Then
		_WinAPI_DeleteObject($hBitmap)
	EndIf

	GUISetState(@SW_SHOW, $hForm)

	Do
	Until GUIGetMsg() = -3

	GUIDelete($hForm)

EndFunc   ;==>_ViewGraph

А вообще, функция Random() в AutoIt довольно скверная, даже при 1.000.000 точек гистограмма как дороги в России.
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Re: [Математика] Рандомный Random

Yashied [?]
Мат. ожидание куда-то убежало
не понял. в смысле убежало? :smile: как задашь, такой и будет. никуда убегать не будет.
и причем здесь Sqrt(2*$Pi)
мм... если мне не изменяет память именной такой нормировочный коэффициент при экспоненте. вообще, я хотел воспроизвести вот эту функцию
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 712
Re: [Математика] Рандомный Random

Посмотри мой пример, мат. ожидание должно быть 0.5 (по центру), а получается нет.
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Re: [Математика] Рандомный Random

Вобщем, вот что я нарыл. Пусть у нас есть два независимых равномерно распределенных числа, то из них можно составить стандартно равномерно распределенных числа следующим образом
Код:
#include <Array.au3>
$Pi = 3.14159265358979
Dim $a[1000][3]
For $i = 0 to 999
	$x = Random(); первое число
	;Sleep(1)
	$y = Random(); второе число
	$a[$i][2] = Sqrt(-2*Log($x))*Sin(2*$Pi*$y); первое число нормально распределенное
	$a[$i][2] = Sqrt(-2*Log($x))*Cos(2*$Pi*$y); второе число нормально распределенное
	$a[$i][1] = $y
	$a[$i][0] = $x
	ConsoleWrite($x & @TAB & $y& @TAB & $a[$i][1] & @CRLF)
Next
_ArrayDisplay($a)

Проверил гистограмму в Excel, получилось вполне себе кошерно.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 712
Re: [Математика] Рандомный Random

Kaster, по каким данным ты построил свою гистограмму?
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Re: [Математика] Рандомный Random

Yashied [?]
Kaster, по каким данным ты построил свою гистограмму?
это частотная характеристика массива $a[1000][2]. там в коде небольшая опечаточка. значения по второму индексу продублированы. таким образом именно в том примере - это гистограмма данных по второму ряду чисел, в коде определяются как
Код:
$a[$i][2] = Sqrt(-2*Log($x))*Cos(2*$Pi*$y)
- но это не принципиально. первый ряд определенный через синус будет иметь то же распределение. соответственно и гистограмма у ней будет такая же
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 712
Re: [Математика] Рандомный Random

Kaster, У меня получается для этой функции вот такая вот гистограмма (на участке от 0 до 1).



???
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Re: [Математика] Рандомный Random

Yashied
мм.. а как ты строишь дисперсию?гистограмму :smile: просто у тебя оси не обозначены, не совсем понятно. у меня это номер интервала и кол-во точек которые попали в этот интервал. вроде как, гистограмма частот именно так определяется.


Добавлено:
Сообщение автоматически объединено:

кстати, проверил на 100к точках. гистограмма идеальная
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 712
Re: [Математика] Рандомный Random

Код:
; Определяем массив для построения гистограммы
Dim $aPoints[100][2] = [[0.0, 0]]

; Разбиваем участок от 0 до 1 на интервалы с шагом 0.01
For $i = 1 To 99
    $aPoints[$i][0] = $aPoints[$i - 1][0] + 0.01
    $aPoints[$i][1] = 0
Next
; Подсчитываем количество попаданий в каждый интервал при выборке 100000
For $i = 1 To 100000
    $Val = _GRandom()
    For $j = 0 To UBound($aPoints) - 1
        If ($Val >= $aPoints[$j][0]) And ($Val <= $aPoints[$j][0] + 0.01) Then
            $aPoints[$j][1] +=1
            ExitLoop
        EndIf
    Next
Next
; Определяем максимум
$Max = 0
For $i = 0 To UBound($aPoints) - 1
    If $Max < $aPoints[$i][1] Then
        $Max = $aPoints[$i][1]
    EndIf
Next
; Нормализуем резултаты
For $i = 0 To UBound($aPoints) - 1
    $aPoints[$i][1] /= $Max
Next

; Здесь массив $aPoints содержит координаты X и Y для построения гистограммы

Func _GRandom() ; Это твоя функция :)
    Return Sqrt(-2 * Log(Random())) * Cos(2 * $Pi * Random())
EndFunc   ;==>_GRandom


Вроде ошибок не нахожу...
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Re: [Математика] Рандомный Random

не совсем понятно с нормализацией. обычно нормализуют чтобы построить гистограмму относительных частот, тогда надо делить на объем выборки. но это не суть. это всего лишь преобразование подобия, форма должна остаться прежней. только опять же, по поводу осей. если ты строишь частоту попадания от значения рандомной точки - то это скорее всего не гистограмма, а обрезанный кусок функции распределения. в твоем случае - это будет стандартно нормально распределенные числа, значит мат-ожидание у ней 0. строить надо от -1 до 1, хотя бы. чтобы увидеть полную картину. должна получиться стандартная шапочка
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 712
Re: [Математика] Рандомный Random

Я понимаю так: делаю N вычислений на участке 0...1, получаю массив из N значений. Затем подсчитываю сколько было попаданий в каждый участок: 0 - 0.01, 0.01 - 0.02, ... , 0.99 - 1. Таким образом получаю координаты для построения графика, где X - центр (у меня левая граница, не суть важно) каждого интервала, а Y - количество попаданий в этот интервал. Вроде так. Следовательно мат. ожидание должно быть по центру - 0.5, а на графике черт знает что. Что здесь не так?
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Re: [Математика] Рандомный Random

Yashied [?]
Что здесь не так?
то что получать ты будешь числа нормально распределенные, стало быть любые из -беск до +беск. а в твоем коде учитываются только те, которые попадут в 0, 1. по хорошему надо строить от мин до макс, и в идеале мин=-макс. но т.к. ты делишь потом на макс все, то строить можно и от -1 до 1. как я и предложил выше. первое что приходит в голову. но в том, что по технике выше с лог и син получаются нормально распределенные числа я уже убедился на все 100 :smile:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 712
Re: [Математика] Рандомный Random

Что-то не так... Нужно просто адаптировать твою функцию к интервалу, заданному функцией Random($Xmin, $Xmax), и с мат. ожиданием, по человечески, в центре этого интервала - ($Xmin + $Xmax) / 2. Дисперсию оставим в покое.

:smile:
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Re: [Математика] Рандомный Random

Yashied [?]
и с мат. ожиданием, по человечески, в центре этого
у стандартно нормально распределенных чисел мат ожидание всегда = 0. какие интервалы, на которых ты бы хотел построить саму кривую не задавал :smile:
для того чтобы перейти в произвольным нормально распределенным числам, нужно сделать преобразование. но на сегодня я все ;D
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 712
Re: [Математика] Рандомный Random

OffTopic:
:sleeping:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 402
Re: [Математика] Рандомный Random

Yashied сказал(а):
:wacko:
Вы тут ребята ракету готовите, к запуску на марс? :laser:

P.S
Кстати, если я не ошибаюсь (а я могу сильно ошибаться :laugh:, т.к данная тема от меня немного(?) далека), вы уже вышли за пределы данной темы...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 712
Часть II

Kaster, вообщем идея заключается в написании функции _GRandom($Min, $Max), имеющая нормальное распределение с мат. ожиданием в центре этого интервала - ($Min + $Max) / 2. Есть идеи?
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Yashied [?]
по идее так
Код:
Local $Min = 0, $Max = 1, $D = 0.1; Задаешь интервал и дисперсию
$M = ($Max + $Min) / 2; Мат ожидание, в принципе любое, но раз ты хочешь чтобы именно в центре :)
$X = Sqrt(-2 * Log(Random())) * Cos(2 * $Pi * Random()); Стандартно норм.... бла бла бла
$Y = ($X - $M) / $D; Произвольное нормальное распределенное число с МО - $M, и дисперсией $D
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 712
Опять что-то не то...

Код:
Sqrt(-2 * Log(Random())) * Cos(2 * $Pi * Random())


Твоя функция выдает следующие результаты:

-0.180007334518589
0.729794747560476
-1.4048312260519
-1.35359019484716
0.483299824784077
0.648392081007206
0.0861799534066718
0.423508151159531
-1.17292896846556
-0.0516247525551346
-1.02630722456185
-0.0733908819746407
-0.659096799336869
0.358246149159045
1.04298418186321
-0.992558100504008
1.54637372359042
-0.368271745247627
-0.662969669510869
0.867572604038532
-2.33057170432556
1.06805057113926
-1.31963882695383
-1.08098091940203
0.330643438742445
0.887404589253342
0.437813855650564
1.3277390561886
-0.377056290598163
0.424263864216916
-1.26897948610788
0.751952743151951
1.27096090913936
-0.702672574928529
-0.304044688638876
1.50019572113675
0.636803506972626
-0.365352340625526
0.101487842052685
-0.484057940988953
-1.40791501444777
-1.3794908473738
-1.72938994978061
-0.498399809234422
0.667929256878677
-1.59881583767489
-0.951115458468474
-1.20146267519419
2.34920560381623
-0.871985962972638
-0.26968090126137
0.449622520483933
-1.85458580197192
-2.67454628850377
-0.55070769989057
0.807647967470131
0.0538567956420015
-1.03605467662948
1.80093407607802
0.647316237540539
-1.77756460121584
1.76813058428496
-0.0349889109971487
1.40567184894444
-0.743615741880751
-0.0529745026329178
-1.43602387160808
0.136240146368731
-0.88944953138276
-0.205387623445289
-0.352840692314351
-0.499682896998218
-0.106476391730804
-0.0574712726850859
-1.46161305785883
-0.0708920708729136
0.303191653353569
-1.40242808249054
0.96324476045029
1.84673953149575
-0.405657269697784
1.65182386313226
-0.650207532659323
-1.28683399231827
1.10207633118084
-0.498521963679114
-0.0949353849793158
1.36916491850797
-0.831683731873023
-3.30325147644318
0.184858174298022
-1.75015084660608
0.328152026475383
0.566184923668834
-0.462332696793597
0.138790055702788
0.3429770775534
-1.05477204539162
1.17121829977228
1.50437958885869

а должна выдавать нормально распределенные случайные числа в диапазоне от $Xmin до $Xmax, в данном случае от 0 до 1 - Random().

:(

И еще предполагается, что $Xmin и $Xmax могут быть отрицательными, поэтому я и написал ($Xmin + $Xmax) / 2.

Kaster, как ее нормализовать к заданному диапазону?

:-\
 
Верх