generate a 'random' number Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

generate a 'random' number

11 Oct 2018, 17:48

Has anyone written a function to generate a pseudo-random number in AutoHotkey? E.g. a short one that is reasonably good. Or a conversion of the C++ code that AutoHotkey uses. Or anything else? Thanks.

An interesting link.
flat assembler - Fast and small Multiplicative Random number generator
https://board.flatassembler.net/topic.php?t=13741
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: generate a 'random' number

12 Oct 2018, 07:14

- Thanks Helgef (and HotKeyIt), I'll take a look when I can.
- I'd still be interested in other approaches, including simple but reasonably good ones. (Normally when I need random numbers, the level of randomness is not critical.)
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: generate a 'random' number

06 Nov 2018, 00:32

- The functions in the link are great, but it deviates quite a bit from the AHK source code. And so I've gone back to the source code and am trying to translate it more literally.
- Going through the source code, one key thing I don't understand is this: if I set the seed, and do Random, and do Random again, and reload the script and do the same thing again, why don't I get exactly the same numbers.
- (And it would be useful to have a script that produces the same random-looking sequence each time, for some situations.)

- I did notice some reference to time functions:
mt19937ar-cok.cpp: GetTickCount
script.h: GetSystemTimeAsFileTime
But I'm still unsure why Random is giving me a different number each time.
- Furthermore, to test that any translation from C++ to AHK is working, I might like to edit the C++ code to compile a custom AHK exe for testing, to give the same values each time. Cheers.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: generate a 'random' number

06 Nov 2018, 02:52

if I set the seed, and do Random, and do Random again, and reload the script and do the same thing again, why don't I get exactly the same numbers.
That would be a bug, more likely though, you are mistaken or I do not understand what you are trying to do.

Cheers.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: generate a 'random' number

06 Nov 2018, 03:28

- Thanks a lot Helgef. Indeed, this script is giving the same number every time.
- This is great, it means that (a) I can proceed with the C++ to AHK conversion, (b) I'm understanding everything that I need to understand.

Code: Select all

q::
Random,, 1337 ;set the seed
Random, vNum ;retrieve the first number (1125387415)
Clipboard .= "`r`n" vNum
MsgBox, % Clipboard
return
- I had the following issue:

Code: Select all

Random , %NewSeed% ;doesn't work
Random,, %NewSeed% ;works
- I've had other issues when using commands without a leading comma, and omitting the first parameter. E.g. for ControlMove/ControlSend/ControlSetText, I used % "":

Code: Select all

ControlSend , %Keys%, ahk_id %hWnd% ;doesn't work
ControlSend % "", %Keys%, ahk_id %hWnd% ;works
ControlSend,, %Keys%, ahk_id %hWnd% ;works
- And when using AHK v2 I had this issue: :crazy:
AHK v2: append to clipboard - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 14&t=58913

- Just for anyone curious, the way Random works is like this: when the script starts, the system time is checked, and based on that, a value is chosen between 0 and 4294967295 (0xFFFFFFFF), called the seed. Each seed has a list of numbers associated with it, like a times table, and each time you use Random, the next number in the list is retrieved and used. The numbers aren't really random!
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: generate a 'random' number

06 Nov 2018, 06:53

Guys.. I dont understand the link between c++ conversion and random number generating ? Can you please shed a light to help?
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: generate a 'random' number

06 Nov 2018, 17:53

At various times for various reasons I've tried to recreate some of the built-in AHK functions (written in C++) as standard AHK functions.

AutoHotkey via DllCall: AutoHotkey functions as custom functions - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=37871
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: generate a 'random' number

06 Nov 2018, 22:11

thank you. So ok, thats alot of work man.. I guess its a super good way to learn programming to recreate all this. I can see the effort!
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: generate a 'random' number  Topic is solved

06 Nov 2018, 22:57

- Here is an attempt at recreating the AHK v2 Random and RandomSeed functions (equivalent to the AHK v1 Random command).

Code: Select all

q:: ;recreate Random and RandomSeed
vSeed := 1337
Random,, % vSeed
JEE_RandomSeed(vSeed)
vMin := 0, vMax := 2147483647
vMin := -2147483648, vMax := 2147483647
vMin := 0.0, vMax := 1.0
vMin := 0.0, vMax := 100.0
vMin := -2147483648.0, vMax := 2147483647.0
vOutput := ""
Loop, 10
{
	Random, vTemp1, % vMin, % vMax
	vTemp2 := JEE_Random(vMin, vMax)
	vOutput .= vTemp1 "`r`n" vTemp2 "`r`n`r`n"
	if !(vTemp1 = vTemp2)
		MsgBox, % "mismatch:`r`n" vTemp1 "`r`n" vTemp2
}
MsgBox, % Clipboard := vOutput
return

e::
vIntervals := 0
DllCall("kernel32\GetSystemTimeAsFileTime", Int64P,vIntervals)
vSeed := vIntervals & 0xFFFFFFFF
vSeed := 1337

Random_init_genrand(vSeed)
MsgBox, % vSeed "`r`n" Random_genrand_int32()

Random,, % vSeed
Random, vNum
MsgBox, % vSeed "`r`n" vNum
return

w::
vNum := 1000000
vNum := 1000
Loop, % 0xFFFFFFFF + 1
{
	ToolTip, % A_Index
	vSeed := A_Index - 1
	Random,, % vSeed
	;vOutput1 := "AHK" "`r`n"
	vOutput1 := ""
	Loop, % vNum
	{
		Random, vTemp
		vOutput1 .= vTemp "`r`n"
	}
	Random_init_genrand(vSeed)
	;vOutput2 := "CUSTOM" "`r`n"
	vOutput2 := ""
	Loop, % vNum
	{
		vTemp := Random_genrand_int32()
		if (vTemp >= 2147483648)
			vTemp -= 2147483648
		vOutput2 .= vTemp "`r`n"
	}
	if !(vOutput1 = vOutput2)
	{
		MsgBox, % "mismatch for seed: " vSeed
		;JEE_WinMergeCompareStrings(vOutput1, vOutput2)
	}
}
MsgBox, % "done"
return

;==================================================

;Random_XXX functions based on AHK source code (mt19937ar-cok.cpp)

;Random - Syntax & Usage | AutoHotkey
;https://autohotkey.com/docs/commands/Random.htm

;/*
;   C++ functions for MT19937, with initialization improved 2002/2/10.
;   Coded by Takuji Nishimura and Makoto Matsumoto.
;   This is a faster version by taking Shawn Cokus's optimization,
;   Matthe Bellew's simplification, Isaku Wada's real version.

;   Before using, initialize the state by using init_genrand(seed)
;   or init_by_array(init_key, key_length).

;   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
;   All rights reserved.

;   Redistribution and use in source and binary forms, with or without
;   modification, are permitted provided that the following conditions
;   are met:

;     1. Redistributions of source code must retain the above copyright
;        notice, this list of conditions and the following disclaimer.

;     2. Redistributions in binary form must reproduce the above copyright
;        notice, this list of conditions and the following disclaimer in the
;        documentation and/or other materials provided with the distribution.

;     3. The names of its contributors may not be used to endorse or promote
;        products derived from this software without specific prior written
;        permission.

;   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
;   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
;   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
;   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
;   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
;   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
;   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
;   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
;   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
;   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
;   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

;   Any feedback is very welcome.
;   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
;   email: [email protected]
;*/

;==================================================

Random_MIXBITS(u,v)
{
	local
	UMASK := 0x80000000
	LMASK := 0x7fffffff
	return (u & UMASK) | (v & LMASK)
}
Random_TWIST(u,v)
{
	local
	MATRIX_A := 0x9908b0df
	return (Random_MIXBITS(u,v) >> 1) ^ ((v&1) ? MATRIX_A : 0)
}
Random_init_genrand(s)
{
	local
	global g_Rand, g_RandState
	static N := 624
	g_Rand := {}
	g_RandState := []
	g_RandState.SetCapacity(N)
	g_RandState.Push(s & 0xffffffff)
	Loop, % N-1
	{
		j := A_Index+1
		temp := (1812433253 * (g_RandState[j-1] ^ (g_RandState[j-1] >> 30)) + j-1)
		g_RandState.Push(temp & 0xffffffff)
	}
	g_Rand.left := 1
	g_Rand.initf := 1
}
Random_next_state()
{
	local
	global g_Rand, g_RandState
	static M := 397, N := 624
	if !IsObject(g_Rand)
		g_Rand := {}
	g_Rand.left := N
	g_Rand.next := 1
	if !g_Rand.initf
	{
		vTickCount := DllCall("kernel32\GetTickCount", UInt)
		Random_init_genrand(vTickCount)
		;vIntervals := 0
		;DllCall("kernel32\GetSystemTimeAsFileTime", Int64P,vIntervals)
		;Random_init_genrand(vIntervals & 0xFFFFFFFF)
	}
	temp := 0
	Loop, % N-M
		temp += 1, g_RandState[temp] := g_RandState[temp+M] ^ Random_TWIST(g_RandState[temp], g_RandState[temp+1])
	Loop, % M-1
		temp += 1, g_RandState[temp] := g_RandState[temp+M-N] ^ Random_TWIST(g_RandState[temp], g_RandState[temp+1])
	temp += 1, g_RandState[temp] := g_RandState[temp+M-N] ^ Random_TWIST(g_RandState[temp], g_RandState.1)
}
Random_genrand_int32()
{
	local
	global g_Rand, g_RandState
	if !IsObject(g_Rand)
		g_Rand := {}
	if (--g_Rand.left == 0)
		Random_next_state()
	y := g_RandState[g_Rand.next++]
	y ^= (y >> 11)
	y ^= (y << 7) & 0x9d2c5680
	y ^= (y << 15) & 0xefc60000
	y ^= (y >> 18)
	return y ;a random number on [0,0xffffffff]-interval
}
Random_genrand_int31()
{
	local
	global g_Rand, g_RandState
	if !IsObject(g_Rand)
		g_Rand := {}
	if (--g_Rand.left == 0)
		Random_next_state()
	y := g_RandState[g_Rand.next++]
	y ^= (y >> 11)
	y ^= (y << 7) & 0x9d2c5680
	y ^= (y << 15) & 0xefc60000
	y ^= (y >> 18)
	return y >> 1 ;a random number on [0,0x7fffffff]-interval
}
Random_genrand_real1()
{
	local
	global g_Rand, g_RandState
	if !IsObject(g_Rand)
		g_Rand := {}
	if (--g_Rand.left == 0)
		Random_next_state()
	y := g_RandState[g_Rand.next++]
	y ^= (y >> 11)
	y ^= (y << 7) & 0x9d2c5680
	y ^= (y << 15) & 0xefc60000
	y ^= (y >> 18)
	return y * (1/4294967295) ;a random number on [0,1]-real-interval
}

;range: 0 to 4294967295
JEE_RandomSeed(vSeed)
{
	local
	Random_init_genrand(vSeed)
}

;range: -2147483648 to 2147483647 (for integers)
;range: no limit (for floats)
JEE_Random(vMin:=0, vMax:=2147483647)
{
	local
	vIsFloat := !!(InStr(vMin, ".") || InStr(vMax, "."))
	if (vMin > vMax)
		vTemp := vMin, vMin := vMax, vMax := vTemp
	if vIsFloat
		return Random_genrand_real1() * (vMax - vMin) + vMin
	return Mod(Random_genrand_int32(), vMax - vMin + 1) + vMin
}
- @DRocks: Thanks.
- Curiously the source code uses GetTickCount in one place, but GetSystemTimeAsFileTime in another.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: generate a 'random' number

15 Nov 2018, 08:34

- I've resolved the issue re. blank initial parameters:
Scripting Language | AutoHotkey
https://autohotkey.com/docs/Language.htm#commands
The comma separating the command name from its parameters is optional, except in the following cases:

•When it's necessary to prevent the line from being interpreted as a legacy assignment or assignment expression.
MsgBox, := This would be an assignment without the comma.

•When the first parameter is blank.
MsgBox,, Second, Third

•When the command is alone at the top of a continuation section.
- I always use an initial comma, and so never experienced the problem before. The only reason I omitted initial commas this time was because I was maintaining Coco's programming style in my 'AHK v2 functions for AHK v1' script.
- I've added a note about the issue here:
jeeswg's documentation extension tutorial - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=33596
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: JoeWinograd, yabab33299 and 124 guests