I didn’t know about this specific syntax you mentioned (import foo.baras baz; what I’m aware and I use frequently is something like e.g. const log = console.log.bind(console)), I’m not even sure if it works as all my import use cases involve something installed from NPM or a relative-folder module file.
But sometimes it’s useful, and better, to have parametrized randomness, as in my helper functions I keep reusing across my personal projects:
(yeah, my choose helper lacks a proper verification of the input parameter, will return undefined if the array is empty or is not an array, but, well, it’s for personal projects so I don’t really worry about that; also I’ve been using Ruby more than I use JS, and Ruby got beautifully native array.sample and Random.rand(a..b))
Second, irand(0, 6) has a higher chance of rolling a 1 than a 0 because the capture area for 1 is [.5, 1.5), while the capture area for 0 is only [0, .5)
Also if you had chosen any other variable names, it wouldn’t have taken me 5 minutes to figure out what these things do.
And one more, if you had swapped the input parameters, and defaulted to n=0, you could call the use case “random number up to 6” with just rand(6) instead of rand(0, 6).
None of that matters in a private project, but… it just itched to point these things out.
Back when I coded that (it’s been years), I opted for the shortest one-liners possible (I often catch myself doing one-liners and code-golfing for the fun of it), with “n” and “x” meaning respectively “miN” and “maX”. Hence why I also do a call to rand inside the irand, so irand is as shortest as possible.
As for the bias towards the mid, it’s by design, because ends up quite similar to the central limit theorem:
Notice how both extremities have lower values while the median (3) got the maximum value (1691). I wanted something behaving similarly to how noise often feels like in real world settings (e.g. SDR radio settings, never truly uniform), hence why the “maX” value is inclusive, it’s purposefully meant to, just like the “miN” value is also inclusive, because they need to be inclusive so it gets to appear amidst the samples.
As a comparison, when I change it to trunc (because floor would behave differently for negative numbers), as in:
…then the sample gets too annoyingly uniform, not even to say about how max (the 6) ends up missing from the samples (thus requiring a x+1 whenever the max value is intended to be inclusive). This may be the best distribution for certain scenarios where uniform randomness is expected, but this doesn’t feel… natural.
That’s also why I implemented this JS flavour in a personal Ruby gem (utils.rb) because Ruby got this annoyingly uniform distribution with its native Random.rand (again, useful sometimes, but not exactly natural):
See how my Ruby’s irand implementation behaves exactly as my JS’s irand do: with this more natural bias towards the middle.
As for the possibility to do irand(x), because the use case often involves having a well-defined range instead of a maximum target value (minimum value isn’t even always zero, but something arbitrary such as e.g. irand(65,65+25) for generating codepoints for alphabet letters), this is why it’s not overloaded so to default n to zero.
@[email protected] @[email protected] @[email protected]
I didn’t know about this specific syntax you mentioned (
import foo.bar as baz; what I’m aware and I use frequently is something like e.g.const log = console.log.bind(console)), I’m not even sure if it works as all myimportuse cases involve something installed from NPM or a relative-folder module file.But sometimes it’s useful, and better, to have parametrized randomness, as in my helper functions I keep reusing across my personal projects:
export const rand = (n, x) => Math.random() * (x - n) + n export const irand = (n, x) => Math.round(rand(n, x)) export const choose = a => a[irand(0, a.length-1)](yeah, my
choosehelper lacks a proper verification of the input parameter, will returnundefinedif the array is empty or is not an array, but, well, it’s for personal projects so I don’t really worry about that; also I’ve been using Ruby more than I use JS, and Ruby got beautifully nativearray.sampleandRandom.rand(a..b))I think
irandshould floor instead of round. First, when you want to generate a random number between 0 and 6 it’s often useful to exclude the 6. (See also https://www.cs.utexas.edu/~EWD/transcriptions/EWD08xx/EWD831.html).Second,
irand(0, 6)has a higher chance of rolling a 1 than a 0 because the capture area for 1 is [.5, 1.5), while the capture area for 0 is only [0, .5)Also if you had chosen any other variable names, it wouldn’t have taken me 5 minutes to figure out what these things do.
And one more, if you had swapped the input parameters, and defaulted to
n=0, you could call the use case “random number up to 6” with justrand(6)instead ofrand(0, 6).None of that matters in a private project, but… it just itched to point these things out.
@[email protected]
Back when I coded that (it’s been years), I opted for the shortest one-liners possible (I often catch myself doing one-liners and code-golfing for the fun of it), with “n” and “x” meaning respectively “miN” and “maX”. Hence why I also do a call to rand inside the irand, so irand is as shortest as possible.
As for the bias towards the mid, it’s by design, because ends up quite similar to the central limit theorem:
> Array.from(Array(10000), _=>irand(0,6)).reduce((p,v)=>({...p, [v]: (p[v]||0)+1}), {}) { '0': 840, '1': 1602, '2': 1658, '3': 1691, '4': 1684, '5': 1687, '6': 838 }Notice how both extremities have lower values while the median (3) got the maximum value (1691). I wanted something behaving similarly to how noise often feels like in real world settings (e.g. SDR radio settings, never truly uniform), hence why the “maX” value is inclusive, it’s purposefully meant to, just like the “miN” value is also inclusive, because they need to be inclusive so it gets to appear amidst the samples.
As a comparison, when I change it to trunc (because floor would behave differently for negative numbers), as in:
> irand = (n, x) => Math.trunc(rand(n, x)) [Function: irand] > Array.from(Array(10000), _=>irand(0,6)).reduce((p,v)=>({...p, [v]: (p[v]||0)+1}), {}) { '0': 1684, '1': 1659, '2': 1685, '3': 1668, '4': 1676, '5': 1628 }…then the sample gets too annoyingly uniform, not even to say about how max (the 6) ends up missing from the samples (thus requiring a x+1 whenever the max value is intended to be inclusive). This may be the best distribution for certain scenarios where uniform randomness is expected, but this doesn’t feel… natural.
That’s also why I implemented this JS flavour in a personal Ruby gem (utils.rb) because Ruby got this annoyingly uniform distribution with its native
Random.rand(again, useful sometimes, but not exactly natural):irb(main):041:0> 10000.times.map{Random.rand(0..6)}.tally.sort{|a,b|a[0]<=>b[0]}.to_h => {0=>1431, 1=>1449, 2=>1395, 3=>1435, 4=>1411, 5=>1465, 6=>1414} irb(main):042:0> def rand(n,x) = Kernel::rand()*(x-n)+n => :rand irb(main):043:0> def irand(n,x) = rand(n,x).round => :irand irb(main):044:0> 10000.times.map{irand(0,6)}.tally.sort{|a,b|a[0]<=>b[0]}.to_h => {0=>892, 1=>1612, 2=>1744, 3=>1643, 4=>1592, 5=>1708, 6=>809}See how my Ruby’s irand implementation behaves exactly as my JS’s irand do: with this more natural bias towards the middle.
As for the possibility to do irand(x), because the use case often involves having a well-defined range instead of a maximum target value (minimum value isn’t even always zero, but something arbitrary such as e.g.
irand(65,65+25)for generating codepoints for alphabet letters), this is why it’s not overloaded so to default n to zero.Thanks for the write-up. Your use case is different from all I’ve ever had. It’s good to be reminded that my world view isn’t universal.