From WikiChip
$rand identifier - mIRC
< mirc‎ | identifiers
Revision as of 03:50, 17 January 2019 by Maroonbells (talk | contribs)

$rand returns a random integer from the specified range. If you supply two strings or characters not beginning with a number, it returns a random character from that range of code points.

Synopsis

$rand(number1,number2)
$rand(char1,char2)

Parameters

number1,number2 = starting/ending range of integers
char1,char2 = starting/ending characters in range of characters. Valid range $chr(1) through $chr(65535)

  • Note: High/Low endpoints of output range can be used in either order.
  • Note: Through v7.54 numbers must be 0 or greater. Starting v7.55 one/both number can be negative

Properties

None

Examples

//echo -a $rand(0,10)

returns a random number from 0 through 10.

//echo -a $rand(A,Z)
returns a random upper case from A through Z
//echo -a $rand(A,z)
returns upper and lower case letters, but also other ASCII characters in that range of code points, including [ \ ] ^ _ `
Random number used as index:
//echo -a Monty Hall opens Door number 2 to reveal a $gettok(goat goat car,$rand(1,3),32)
 
display all unique values returned within 100 random values:
//var %i 100 | var %s | while (%i) { var %a $rand($chr(33),$chr(126)) | if (%a !isincs %s) var %s %s %a | dec %i } | echo -a $sorttokcs(%s,32)
 
Displays frequency distribution. Random does not mean equal outcomes. It's rare for a dice to roll exactly 10K 6's in 60K rolls:
//var %i = 60000 , %low 1 , %high 6 | var %nums $str(0 $chr(32),$calc(1+%high -%low)) | var %ticks $ticks | while (%i) { var %a $rand(%low,%high) | var %t $calc(1+%a -%low) | var %b $gettok(%nums,%t,32) | inc %b | var %nums $puttok(%nums,%b,%t,32) | dec %i } | var %c 1 | var %i %low | while ($gettok(%nums,%c,32) != $null) { var %b $gettok(%nums,%c,32) | var %nums $puttok(%nums,$+(%i,:,%b),%c,32) | inc %i | inc %c } | echo -a time: $+ $calc($ticks - %ticks) $+ ms-> %nums
 
Valid codepoints are 1 through 65535:
//var %i 10000 , %s , %low 9100 , %high $calc(%low +999) | while (%i) { var %a $rand($chr(%low),$chr(%high)) | if (%a !isincs %s) var %s %s %a | dec %i } | echo -a $numtok(%s,32) tokens: $sorttok(%s,32)

Notes

  • It does not matter which value is higher, $rand(a,z) is same as $rand(z,a)
  • If either value is not 0 or positive, the first character of both value is considered the starting/ending codepoint.
  • Through v7.54, if one of the numbers is negative, it's treated as if the value was the hyphen's non-numeric codepoint 45.
  • If either number has a fraction, it's rounded (not $int) to the nearest integer.
  • $rand(number,non-number) returns $null, so if you need ASCII range from '1' through 'Z', use $chr($rand($asc(1),$asc(Z)))
  • $rand(foo,bar) returns codepoints from the first character of each value, 'b' through 'f'
  • $rand does not claim to create cryptographically secure output. For that type of random number, you can consider using $rands and/or use up to 53 bits of the output of a $hmac digest which uses a random message and a secret key, and use $base to translate that string into a base 10 number.
  • As of v6.35, valid range was 0-999999999999 (12 9's approx 2^40), and as of v7.54 the valid range was 0 through 99999999999999 (slightly greater than 2^46.5). But a bug does not allow all values within that range to be returned. Even as low as a 24-bit range $rand(0,16777215), nearly a third of v7.54 outputs appear to be rarely or never returned. Those versions also had a modulo bias favoring lower numbers for some range sizes, which can be hard to detect except at large ranges.

Demonstrating bias in v7.54: Paste the command below into any editbox, and the distribution within the range from low to high appears fairly random. However change the 14 9's into 14 6's and 2/3rds of the outputs are in the lower regions of the range. For older versions whose valid range is only as large as 12 9's, shorten the string of 9's to length 12.

//var -s %pockets 256 , %array $str(0 $chr(32),%pockets) , %i 25600 , %max 99999999999999 , %div %max / %pockets | while (%i) { var %t $calc(1+ ($rand(0,%max) / %div)) , %a $gettok(%array,%t,32) + 1 , %array $puttok(%array,%a,%t,32) | dec %i } | echo -a %array = $calc($replace(%array,$chr(32),+))

If worried that your range is large enough to display either bias, you can use the slower randpatch alias to create more accurate output using the output from 5 smaller ranges. You can test randpatch by substituting it in place of $rand in the above command.

alias randpatch {
  if (($1 !isnum) || ($2 !isnum)) goto error | var %lo $int($1) , %hi $int($2)
  var %diff %hi - %lo , %out_range %diff + 1 , %max.val $calc(2^53-1)
  if ((%hi > %max.val) || (%diff > %max.val) || (%lo < $calc(-(2^53)))) goto error
  var %throwaway_above $calc(%max.val - (((%max.val % %out_range) + 1) % %out_range) )
  var %int53 $get_53bit_rand_num
  while (%int53 > %throwaway_above) { var %int53 $get_53bit_rand_num }
  return $calc(%lo + (%int53 % %out_range))
  :error | echo -sc info2 *$randpatch(Num1,Num2) MinN1:-2^53 MaxN2/range.max:+2^53-1 | halt
}
alias -l get_53bit_rand_num {
  return $calc($r(0,255) + $r(0,2047) * 256 + $r(0,2047) * 524288 + $r(0,2047) * 1073741824 + $r(0,4095) * 2199023255552)
} ; 53bit value from joining bit sizes 12:11:11:11:8

Compatibility

Added: mIRC v2.1a
Added on: 28 Feb 1995
Note: Unless otherwise stated, this was the date of original functionality.
Further enhancements may have been made in later versions.

See also