Using Math.random flexibly

2019-05-14 16:12发布

问题:

I would like to create a 4 letter long string, RANDOMLY containing any of the letters from the string: "ROYGBV".

What I've done is this:

function generateSolution(){
    var colors = "ROYGBV";
    var str = "";
    for (var i=0; i<4; i++) {
        var loc = Math.ceil( Math.random()*colors.length );
        str += colors.charAt(loc);
    }

    return str;
}

But this doesn't seem right, why is this?

also, this is from the exercise's solution:

str += colors.charAt((Math.random() * 6) | 0);

I used Math.ceil in my solution to prevent randoming floats like 4.333123 and so on. How does this solution work, without rounding the randomed numbers?

Also, what does the | operator mean? and how does the randomization in the second solution actually work?

回答1:

The | is the bitwise OR operator. Since bitwise operations in JavaScript only work with 32-bit integers, that's a shorthand way of rounding a a number towards 0. In your case it's equivalent to this:

colors.charAt(Math.floor((Math.random() * 6)));

The number needs to be floored instead of rounded up, as you are currently doing with ceil, or you will miss the first element of the array (which is at index 0).

Here's the full details of the conversion to integer from the spec:

The production A : A @ B, where @ is one of the bitwise operators in the productions above, is evaluated as follows:

  1. Let lref be the result of evaluating A.
  2. Let lval be GetValue(lref).
  3. Let rref be the result of evaluating B.
  4. Let rval be GetValue(rref).
  5. Let lnum be ToInt32(lval).
  6. Let rnum be ToInt32(rval).
  7. Return the result of applying the bitwise operator @ to lnum and rnum. The result is a signed 32 bit integer.


回答2:

You want Math.floor() instead of Math.ceil(). Javascript arrays are zero-based, so you want values between 0 and 5.



回答3:

Try this

function generateSolution() {
    var colors = "ROYGBV",
        str = "",
        l = colors.length,
        i = 0;

    while (i < 4) {
        var loc = Math.floor(Math.random() * l);
        str += colors.charAt(loc);

        i += 1;
    }

    return str;
}

console.log(generateSolution());

On jsiddle

You need Math.floor, the | is just a bitwise method of performing a 32bit floor