28

Possible Duplicate:
Generating random numbers in Javascript in a specific range?

How can i get a random value between, for example, from -99 to 99, excluding 0?

Community
  • 1
  • 1
user1835929
  • 341
  • 1
  • 3
  • 4

3 Answers3

62
var num = Math.floor(Math.random()*99) + 1; // this will get a number between 1 and 99;
num *= Math.round(Math.random()) ? 1 : -1; // this will add minus sign in 50% of cases

Altogether

var ranNum = Math.ceil(Math.random() * 99) * (Math.round(Math.random()) ? 1 : -1)
oldboy
  • 5,729
  • 6
  • 38
  • 86
LittleSweetSeas
  • 6,786
  • 2
  • 21
  • 26
8

This returns what you want

function getNonZeroRandomNumber(){
    var random = Math.floor(Math.random()*199) - 99;
    if(random==0) return getNonZeroRandomNumber();
    return random;
}

Here's a functional fiddle

EDIT

To contribute for future readers with a little debate happened in the comments which the user @MarkDickinson made a indeed relevant contribution to my first code posted, I've decided to make another fiddle with a fast comparison between using Math.floor() and Math.round() functions to return the value the op wanted.

First Scenario: Using var random = Math.round(Math.random()*198) - 99; (My first suggestion)

function getNonZeroRandomNumberWithMathRound(){
    var random = Math.round(Math.random()*198) - 99;
    if(random==0) return getNonZeroRandomNumber();
    return random;
}

Second scenario: Using var random=Math.floor(Math.random()*199) - 99; (Mark suggestion)

function getNonZeroRandomNumberWithMathFloor(){
    var random = Math.floor(Math.random()*199) - 99;
    if(random==0) return getNonZeroRandomNumber();
    return random;
}

Methodology

Since it's a short debate I've chosen fiddle.net to do the comparison.

The test consists of running the above functions 100.000 times and then retrieving how much times the extreme numbers 99 and -99 would appear against a other number, let's say 33 and -33.

The test will then give a simple output consisting of the percentage of appearances from 99 and -99 and the percentage of appearances of 33 and -33.

It'll be used the Webkit implementation from Safari 6.0.2 to the give the output from this answer but anyone can test with your favourite browser late on fiddle.net

Result from first scenario:

  • Percentage of normal ocurrences:0.97%
  • Percentage of extreme ocurrences:0.52%
  • Percentage of extreme ocurrences relative to normal ocurrences:53.4% // Half the chances indeed

Result from second scenario:

  • Percentage of normal ocurrences:1.052%
  • Percentage of extreme ocurrences:0.974%
  • Percentage of extreme ocurrences relative to normal ocurrences:92% //Closer of a fair result with a minimal standard deviation

The result can be seen here: http://jsfiddle.net/brunovieira/LrXqh/

Community
  • 1
  • 1
Bruno Vieira
  • 3,884
  • 1
  • 23
  • 35
  • 2
    I think you want `199` rather than `188`. – Mark Dickinson Nov 19 '12 at 18:23
  • I think I want 198! Just a typo! – Bruno Vieira Nov 19 '12 at 18:26
  • No, you need `199` if you want to include both `-99` and `99` as possibilities. If you use `198` then there's no way for `99` to come up (at least, not with any reasonable probability). – Mark Dickinson Nov 19 '12 at 18:28
  • I did mean 198 in my answer, but you are right that it wouldn't never return 99. So I'll change from `Math.floor` to `Math.round()`, which will solve the problem. Thanks for noticing by the way – Bruno Vieira Nov 19 '12 at 18:35
  • 1
    Aargh! But with `Math.round`, `-99` and `99` are half as likely to appear as the other values! (Test it if you don't believe me :-) You really *do* want `199` and `Math.floor`! – Mark Dickinson Nov 19 '12 at 18:41
  • I'm testing in this right moment, I'll update the fiddle and the answer with the statistics I found – Bruno Vieira Nov 19 '12 at 18:45
  • Yes, you are right. I'll just update my answer to use Math.floor and 199. Thanks by the way, living and learning – Bruno Vieira Nov 19 '12 at 18:53
  • @MarkDickinson Now I've tested and posted the results. Thanks again – Bruno Vieira Nov 19 '12 at 19:36
  • Please don't suggest this. Even with such lax constraint as 1 number vs. 199, your function have non-zero chance to cause stack overflow. Generally people who get into mindset "reroll random if it doesn't match constraint" will sooner or later will be hit hard with numerous excessive recomputations if constraints are sufficiently tight. – Oleg V. Volkov Nov 21 '12 at 07:14
4

Here's a generalized solution that will let you set the boundaries, and opt in/out of including the 0.

var pos = 99,
    neg = 99,
    includeZero = false,
    result;

do result = Math.ceil(Math.random() * (pos + neg)) - neg;
while (includeZero === false && result === 0);

The pos and neg values are inclusive.

This way there's no requirement that the positive and negative ranges be balanced.


Or if you're worried about the rerun due to a single excluded value, you can just make the initial range less by one, and add 1 to any result greater than or equal to 0.

var pos = 5,
    neg = 5,
    result;

result = Math.floor(Math.random() * (pos + neg)) - neg;
result = result < 0 ? result : result + 1;

That last line could be shorter if you prefer:

result += (result >= 0)
I Hate Lazy
  • 47,415
  • 13
  • 86
  • 77
  • `pos = 1 neg = 1`. Can you predict how many cycles it will waste rerolling? Now imagine that "gap" is wider than "correct result". – Oleg V. Volkov Nov 21 '12 at 07:14
  • @OlegV.Volkov: As is often the case, this is not the right solution for every problem. But it's easy enough to tweak for a narrow range. Of course for a `-1` to `1` range excluding the `0`, we would just do `Math.random() < .5 : -1 : 1;` – I Hate Lazy Nov 21 '12 at 15:29
  • so you need to be aware of whether the number you are passing is positive or negative, rather than just any range? (neg - neg or pos - pos) – Dominic Mar 20 '18 at 17:42