Skip to main content

News

Topic: Avoiding zeroes when generating random numbers (Read 3204 times) previous topic - next topic

Avoiding zeroes when generating random numbers
when using
Code: (javascript) [Select]
var damage = Math.floor(Math.random()*6); 

for example,

zero also comes up sometimes, is there anyway to get rid of it? Cos' getting zero for damage kinda sucks :P

Edit: fixed JS tags - radnen
  • Last Edit: July 07, 2013, 12:42:58 am by Radnen

Re: Avoiding zeroes when generating random numbers
Reply #1
Code: (javascript) [Select]
var damage = 1 + Math.floor(Math.random() * 5); // Generate a number `n` such that  0 <= n <= 4 but then add 1 to it

Code: (javascript) [Select]
var damage = Math.max(1, Math.floor(Math.random() * 6)); // Pick the larger of 1 and a number `n` (0 <= n <= 5)

Code: (javascript) [Select]
var damage = Math.floor(Math.random() * 6) || 1; // 0 is false, so if the random number is 0 that will be `0 || 1` which is 1


Take your pick.
  • Last Edit: July 06, 2013, 03:48:14 pm by alpha123

  • N E O
  • [*][*][*][*][*]
  • Administrator
  • Senior Administrator
Re: Avoiding zeroes when generating random numbers
Reply #2
In all fairness I'd likely only recommend alpha123's first code block since the second and third weigh it so it's twice as likely to pick 1.

Re: Avoiding zeroes when generating random numbers
Reply #3

In all fairness I'd likely only recommend alpha123's first code block since the second and third weigh it so it's twice as likely to pick 1.

Ah, that's true - I didn't think about that. Definitely the first one then.

Too bad Math.ceil(Math.random() * 5) won't work since Math.random() spec'ed to return n where 0 <= n < 1.
Although
Code: (javascript) [Select]
var damage = Math.ceil(Math.random() * 5) || 1;
will work. :)
Bah, never mind - that suffers the same bias as the 2nd and 3rd solutions. :/
  • Last Edit: July 07, 2013, 01:18:47 am by alpha123

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: Avoiding zeroes when generating random numbers
Reply #4
It's spec'd to return 0 <= n <= 1 that because it's impossible to get a 0 or 1 with a LCRNG, the excersise is left to the reader. :P
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

Re: Avoiding zeroes when generating random numbers
Reply #5

Code: (javascript) [Select]
var damage = 1 + Math.floor(Math.random() * 5); // Generate a number `n` such that  0 <= n <= 4 but then add 1 to it



I always thought that was the standard solution, anyway.

On the other hand, if you are using this for a damage calculation, perhaps having a double weight on a result of 1 wouldn't be a bad thing. It would be a single point of pity-damage, without changing the rest of the distribution. Well, it all depends on what you are trying to do.

Re: Avoiding zeroes when generating random numbers
Reply #6

It's spec'd to return 0 <= n <= 1 that because it's impossible to get a 0 or 1 with a LCRNG, the excersise is left to the reader. :P

That's 0 <= n < 1, but the spec does not care how it's implemented. SpiderMonkey and I believe V8 happen to use LCRNGs, but that's an implementation detail and you shouldn't rely on that. However if that is the case (I don't know much about pseudorandom number generation, so I'll take your word for it) Math.ceil(Math.random() * 5) would work, correct?

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: Avoiding zeroes when generating random numbers
Reply #7
Oops, yeah you are right. 0 <= n < 1 Silly me, :)

Quick-Soure:
http://en.wikipedia.org/wiki/Linear_congruential_generator
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Avoiding zeroes when generating random numbers
Reply #8

However if that is the case (I don't know much about pseudorandom number generation, so I'll take your word for it) Math.ceil(Math.random() * 5) would work, correct?


It's been my understanding that you should always implement ranged randoms using floor, regardless of the actual range you need.  Supposedly using either round or ceil will skew the distribution to something other than uniform.

However, there's another caveat: Regardless of whether you use floor, ceil or round, due to floating point rounding issues, there's a very small chance (something on the order of 1 in 2^60 IIRC) that you could get a number one higher than your upper bound.  For that reason, this is the method I use:

Code: (javascript) [Select]
var rnd = low + Math.min(Math.floor(Math.random() * (high - low + 1)), high)
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

Re: Avoiding zeroes when generating random numbers
Reply #9

However, there's another caveat: Regardless of whether you use floor, ceil or round, due to floating point rounding issues, there's a very small chance (something on the order of 1 in 2^60 IIRC) that you could get a number one higher than your upper bound.  For that reason, this is the method I use:

Code: (javascript) [Select]
var rnd = low + Math.min(Math.floor(Math.random() * (high - low + 1)), high)



Are you sure this applies to JS?

Also, 2^60 is such a small chance (really, really small...) that I wouldn't even bother with that. There's also a chance that HDD errors will corrupt your source code and make the high range one integer higher, that the CPU or RAM will have a hard error (unless you have ECC memory, then there would also have to be an ECC error, which is still possible) and produce a garbage result somewhere, etc. ...I don't think it's really worth putting that into your code.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Avoiding zeroes when generating random numbers
Reply #10
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random

From the top of the Examples section: "Note that as numbers in JavaScript are IEEE 754 floating point numbers with round-to-nearest-even behavior, these ranges, excluding the one for Math.random() itself, aren't exact, and depending on the bounds it's possible in extremely rare cases (on the order of 1 in 2^62) to calculate the usually-excluded upper bound."

Considering that in certain scenarios in Specs (enemy AI, notably, when choosing a random move), I'm using the generated number to index into an array, I figure the extra min() call can't hurt.
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

Re: Avoiding zeroes when generating random numbers
Reply #11
Fair enough. But if I put that into a game, I might be tempted to just let the player instantly win the battle if they got lucky on the order of 1/(2^62)!

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Avoiding zeroes when generating random numbers
Reply #12
I'm thorough, what can I say. :)  If it's a bug I can prevent without much effort, I'll account for it.  In fact, the smaller the (nonzero) odds of something like this occurring, the more likely I am to account for it.  Try to reduce the "sufficiently advanced machine" factor, you know?
  • Last Edit: July 08, 2013, 12:08:38 am by Lord English
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan