1

I recently wrote the code to generate 10 characters randomly. Math.random() gives a decimal to toString(36) and all the numbers will be replaced.

Math.random().toString(36).replace(/[^a-z]+/g,'').substr(1,10);

Does anybody have a hint why Firefox (47.0) and Chrome (51) don't handle this equally?

Chrome tests:

Math.random().toString(36).replace(/[^a-z]+/g,'').substr(1,10);
"spkcirhyzb"
"gcqbrmulxe"
"sallvbzqbk"
"pcdcufhqet"
"knfffqsytm"

Firefox tests:

Math.random().toString(36).replace(/[^a-z]+/g,'').substr(1,10);
"zxntpvn"
"hebfyxlt"
"zclj"
"ormtqw"
"cfbsnye"

Live version:

for (var n = 0; n < 5; ++n) {
  console.log(Math.random().toString(36).replace(/[^a-z]+/g,'').substr(1,10));
}

UPDATE (string average):

var test;
  var count = 0;
  for (var n = 0; n < 1000; ++n) {
      test = Math.random().toString(36).replace(/[^a-z]+/g,'').substr(1,10);
      count += test.length;
  }
  console.log(count);
  console.log(count/1000);

My results:

Chrome - 9.999

Firefox - 6.794

3
  • 2
    Just conceptually... you can never guarantee the length of the resulting string, since the amount of a-z characters in the string is entirely random. Commented Jun 29, 2016 at 8:46
  • @deceze thats right, but see the update above, the two browsers handle this enormeours different Commented Jun 29, 2016 at 8:53
  • 1
    Yes, that compounds the problem, and it's a valid question why Number.toString behaves differently. I'm just pointing out that you shouldn't be using this algorithm in the first place. Commented Jun 29, 2016 at 8:55

2 Answers 2

5

Because Chrome's implementation of Number#toString(36) outputs more digits than Firefox's. Consider the number 0.9112907907957448:

Chrome:  0.wt16lcd3ae3m96qx2a3v7vi
Firefox: 0.wt16lcd3ae

You can try it here:

console.log((0.9112907907957448).toString(36));

The spec says the algorithm can be implementation-dependent, it just has to be a "generalization" of ToString Applied To Number Type. Apparently the V8 team (Chrome's JavaScript engine) and the SpiderMonkey team (Firefox's) differ in their interpretations.

The rules for converting IEEE-754 double-precision binary floating point ("double") numbers to strings are complex, because doubles routinely do not precisely store the value that we think of them as storing. For instance, 0.1 is not really 0.1 (which leads to the famous 0.1 + 0.2 != 0.3 issue). It's really, really close to 0.1, but it isn't 0.1. So in theory, (0.1).toString() should output 0.1000000000000000055511151231257827021181583404541015625 (I think that's the right value). In general, though, algorithms that create strings for these values work to the rule that they only output enough digits that if you took that string and converted it back to a floating-point double, you'd get the same floating-point double. That is, even though 0.1 isn't exactly 0.1, it's all the digits you need to get back to the original double value that's very nearly 0.1. Apparently Chrome's implementation of toString in base 36 outputs more digits than that, probably in accordance with "NOTE 2" on the second link above, but I'm not an expert.

The technique is fundamentally flawed in any case: You're taking a string with a near-purely random series of letters and digits and removing the digits, then expecting to get at least ten remaining characters. There's no way to be sure that's actually going to be true, not even on Chrome.

Sign up to request clarification or add additional context in comments.

Comments

1

This is a working solution for your initial question on generating a random string of 10 characters.

As T. J Crowder has pointed out, your solution won't work in any browser as you are expecting it to work.

var chars = "abcdefghijklmnopqrstuvwxyz";
var str = '';
for (var i = 0; i < 10; i++) {
    str += chars[Math.floor(Math.random() * chars.length)];
}
                       
console.log(str);

3 Comments

thanks a lot! one thing you are missing is a pair of brackets str += chars[Math.floor(Math.random() * (chars.length -1))]; since the substraction should be taken first
You shouldn't have that -1 in there
@Kruga you are right, Math.random() returns a number between [0,1)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.