DEV Community

Cover image for How do you do random?
David J Eddy
David J Eddy

Posted on Edited on

How do you do random?

I was watching a VueJS tutorial and was surprised at what it takes in ECMAscript to generate a random integer between 0 and 10.

Math.floor(Math.random() * 10);
🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน 🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน

In PHP it takes

mt_rand(0, 10);
🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน 🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน

In your favorite language what does it take to generate an integer between 0 and 10?

Top comments (48)

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
tetri profile image
Tetri Mesquita •

const random = 7;

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
sleepyfran profile image
Fran González •

xkcd.com/221/

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
qm3ster profile image
Mihail Malo •

Pfff, everyone knows random is 4 not 7.

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
tetri profile image
Tetri Mesquita •

Pfff, you need update your mindset 🤨

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน Thread
 
qm3ster profile image
Mihail Malo • • Edited

Updates just break everything.
How can you know that no consumer of your code assumes it will be 4?
Sure, you claimed it is random, in the "documentation", but it's not like that ever works.

There are probably children out there holding down spacebar to stay warm in the winter! YOUR UPDATE MURDERS CHILDREN.

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
jsn1nj4 profile image
Elliot Derhay •

🤣

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
yaser profile image
Yaser Al-Najjar •

You made my day 🤣🤣

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
joelnet profile image
JavaScript Joel • • Edited

Math.random() produces a random float (all JavaScript numbers are of type float) from 0 to 1.

Adding the requirement of 0-10 means you have to multiply by 10 or * 10.

The last requirement was the number must be an Integer, which is the math.floor.

Of course, if you only wanted a random float between 0 and 1, it would be just one call.

And in PHP if you wanted a random float between 0 and 1, you would also have to do more work: Random Float between 0 and 1 in PHP

So the complexity actually comes from the requirements you give it.

But asking for a random integer is a common task. So it's handy to create function and keep it in your library. Don't go sprinkling Math.floor(Math.random() * 10) randomly around your codebase :D

const pseudoRandomInteger = (start, end) =>
  start + Math.floor(Math.random() * (end - start))

P.S. I prefixed this with pseudo because there is no true Random in JavaScript. This is very important when it comes to cryptography. Google PRNG if you want to learn more.

For a cryptographically strong random value, you might want to look into Crypto.getRandomValues()

Cheers!

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
david_j_eddy profile image
David J Eddy •
...the complexity actually comes from the requirement...

I wish PM's understood this more.

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
krofdrakula profile image
Klemen Slavič •

There's a bug in your example; if the output is supposed to be [start, end), then the correct implementation is:

const pseudoRandomInteger = (start, end) =>
  start + Math.floor(Math.random() * (end - start));

✌😉

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
joelnet profile image
JavaScript Joel •

I probably should have run it once. lol.

I gotta stop typing code directly into editors.

Good catch!

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
jochemstoel profile image
Jochem Stoel •
const between = (min, max) => Math.floor(Math.random() * max) + min
🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
krofdrakula profile image
Klemen Slavič • • Edited

There is a subtle bug to consider with your code, though. If you want to guarantee an even spread among the numbers in the set of [0, 10], you'll have problems with 10 never showing up in your histogram. The reason for this is that the random value will almost never be exactly 1, as most PRNGs will actually output something in the range of [0, 1) (note the non-inclusiveness of 1 in the return values).

To correct that problem, you have to be a little smarter about how you map the [0,1] interval to buckets of integers:

const rand = (max) => Math.floor(Math.random() * (max + 1 - Number.EPSILON));

In the case of 10, you'll be multiplying a number in the [0,1] range to something that's just under 11. Number.EPSILON is the smallest float fraction that JavaScript numbers can express, so it's as close as the JavaScript number precision gets. And because the number 11 is never a value that appears in the output, Math.floor will never return anything above 10, guaranteed.

Of course, if your PRNG never returns 1 in its output, it's safe to just do max + 1. :)

Here's an illustration:

repl.it/@KrofDrakula/safeRandom

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
jsn1nj4 profile image
Elliot Derhay •

What about using Math.round() in place of Math.floor() in the original?

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
krofdrakula profile image
Klemen Slavič •

In that case, 0 and 10 would appear with about 50% the frequency of every other element.

If you imagine the number line after multiplying by 10, you'll understand what I mean:

0                    1                    2
|--------------------|--------------------|---....

<---------0---------><---------1---------><---....   Math.floor()
0---------><---------1---------><---------2---....   Math.round()
0<--------1----------><--------2----------><--....   Math.ceil()

This diagram shows you which floats map to which integer with different functions. As you can see, in the case of Math.round(), 0 has only half the length of every other number, so it would appear half as often. Same goes for 10 at the end of the interval:

9                    10
|--------------------|

9---------><--------10    Math.round()
<----------9--------->    Math.floor()

While 10 would appear in the resulting histogram, its frequency would be about half the frequency of every other non-zero integer.

FYI, Math.round() is just:

const round = n => Math.floor(n + 0.5);

You're effectively just shifting the mapping from floats to integers, but you're not making room for the max number. To have even distribution, you must have all intervals of equal length, and all the intervals covered by the scaled random number interval.

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
krofdrakula profile image
Klemen Slavič •

Also, try out the above repl.it link, you can make your own random functions to see if your hunches are correct. :)

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน Thread
 
jsn1nj4 profile image
Elliot Derhay •

I'm on my smartphone at the moment, but thanks. Your other response makes a lot of sense. That's something I hadn't thought about before.

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
dmiracle profile image
Dylan Miracle •

Typically don't people mean the set of numbers [0, 9] when they say they want a random int between 0 and 10? I would assume they want something out of 10 vs something out of 11

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
krofdrakula profile image
Klemen Slavič •

Well that is where your specification definition alarm bells should start ringing like crazy. We don't have a precise mathematical definition for ranges and sets like this in everyday language among lay folk, therefore you have to clarify what you mean. The example I gave above explicitly lays out the expectations, which the original text hadn't.

Technically speaking saying "between 0 and 10" could mean (0, 10), [0, 10], (0, 10] or [0, 10). In most conversations I've had, people tend to treat ranges as inclusive, so [0, 10] would probably be my best guess, but that's just anecdotal evidence on my part, and should always be checked.

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
biros profile image
Boris Jamot ✊ / •
cat /dev/random 
🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
zeerorg profile image
Rishabh Gupta •

Going the OG route

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
thebadgateway profile image
Will F •

Python has a few options, including the numpy module. Regardless of language, however, it often only takes a ~20 lines to define a pseudo-random (in numerical math we avoid saying "random") number generator method. Here is an implementation of the so-called Mersenne twister:

def rando(n, seed, S = [0, 10, 'integer']):
    i = int(16807)
    j = int(2147483647)
    u_list = []
    if S[2] == 'real':
        for k in range(n):
            seed = (i * seed) % j
            u = (S[1] - S[0]) * (float(seed) / float(j)) + S[0]
            u_list.append(u)
        return u_list
    elif S[2] == 'integer':
        for k in range(n):
            seed = (i * seed) % j
            u = int((S[1] - S[0] + 1) * (float(seed) / float(j)) + S[0])
            u_list.append(u)
        return u_list
    else:
        print('Set of numbers to draw from is undefined')

In this method, we declare two integers, i (16807 = 75), and j (the Mersenne prime). In specifying the arguments n (number of psuedo-random numbers desired), seed (for repeatability of the pseudo-random numbers), and S (min, max, types to be generated), what is repeatedly happening (depending on n) is that we are taking the remainder of (seed * i) and j, and dividing by j; over and over. This implementation of the Mersenne Twister is good for about 230 random numbers before it repeats itself. :)

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
rhymes profile image
rhymes • • Edited

Python:

import random
random.randint(0, 10)

Ruby:

rand(11)

Go:

import "math/rand"

func main() {
    rand.Intn(11)
}

None of these are cryptographically secure though

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
zeerorg profile image
Rishabh Gupta •

Python has a cryptographically secure library called "secrets", which I use a lot :-P

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
rhymes profile image
rhymes •

Yeah secrets is very useful and has a clear API

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
rrampage profile image
Raunak Ramakrishnan • • Edited

APL:

⍝ `? n` generates random number between 1 and n, both inclusive
(? 10) -1
⍝ If we need more than 1 number, use `⍴` function like:
(? 4⍴ 10) -1
⍝ In above code, x⍴y gives you an array of y's of length x

I am a beginner in this language but it is fascinating at how succinct and elegant some constructs are.

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
bgadrian profile image
Adrian B.G. •

Others responded on-topic, so I would add an off-topic :)

I do not build a JS project without Lodash (or something similar), it covers the basic needs and lacks of JS, acting like a Standard library in other languages. A few of them are related to random

_.random([lower=0], [upper=1], [floating])

_.sample(collection) //get a random element
_.sampleSize(collection, [n=1])

But, statistically speaking, taking a float random and truncating it to just a small integer range it's like buying a Ferrari for commuting, just saying :D Most of the times is a waste of resources.

Devs should be more careful at the distributions, most of the cases the code will be used for a few values and a small range of values, which will lead to very not-so-random results.

If the random results will affect the User Experience you should think twice of using it, the screwed distribution will affect your sales and KPIs in unknown ways, most likely negative, and there are always better alternatives, that require more resources to implement of course.

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
kip13 profile image
kip •

From a terminal can be(no for encrypt things):

> shuf -i 0-10 -n 1
4
>
🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
david_j_eddy profile image
David J Eddy •

They see me shuffling. LMFAO

🏆 ยอดนิยม: david j eddy/how do you do random - ประเด็นร้อน
 
scottishross profile image
Ross Henderson •

In PL/SQL:

A random number.

select DBMS_RANDOM.random from dual;
--Result: -860942438

A random round number.

select round(DBMS_RANDOM.random) from dual;
--Result: 1096364454

A random number between two values.

select round(DBMS_RANDOM.value(0, 100)) from dual;
--Result: 54