This is a follow-up question to the one I asked previously, Is this JS Unique ID Generator Unreliable? (Getting collisions).
In the scriptlet below I'm generating 10000 random numbers using 2 methods. Method 1 is a straight random number up to 10^6, while Method 2 concatenates that random number up to 10^6 (same idea as in [1]) with the current JS Date().time() timestamp. Also there's Method [3] which only does the Math.round on the RNG rather than the whole concatenated result.
My question is, if you keep clicking the test button, you see that [1] always produces 10000 unique numbers but [2] produces ~9500 no matter what. [3] produces ~9900 but never the max either. Why is that? The chances of getting a +/-1 from a previous random number in [0..10^6] and having that mixed with the timestamp of exactly the opposite +/-1 for the timestamp concatenation are impossible. We are generating pretty much on the same millisecond in a loop. 10^6 is a huge limit, much bigger than in my original question, and we know that's true because Method [1] works perfectly.
Is there truncation of some kind of going on, which trims the string and makes it more likely to get duplicates? Paradoxically, a smaller string works better than a larger string using the same RNG inside it. But if there's no truncation, I would expect results to be 100% as in [1].
function run() { var nums1 = new Set(), nums2 = new Set(), nums3 = new Set(); for (var i = 0; i < 10000; i++) { nums1.add(random10to6th()); } for (var i = 0; i < 10000; i++) { nums2.add(random10to6th_concatToTimestamp()); } for (var i = 0; i < 10000; i++) { nums3.add(random10to6th_concatToTimestamp_roundRNGOnly()); } console.clear(); console.log('Random 10^6 Unique set: ' + nums1.size); console.log('Random 10^6 and Concat to Date().time() Unique set: ' + nums2.size); console.log('Random 10^6 and Concat to Date().time(), Round RNG Only Unique set: ' + nums3.size); function random10to6th() { return Math.random() * Math.pow(10, 6); } function random10to6th_concatToTimestamp() { return Math.round(new Date().getTime() + '' + (Math.random() * Math.pow(10, 6))); } } function random10to6th_concatToTimestamp_roundRNGOnly() { return new Date().getTime() + '' + Math.round(Math.random() * Math.pow(10, 6)); } <button onclick="run()">Run Algorithms</button> <p>(Keep clicking this button)</p>
.lengthof an array see How do I add 1 to a big integer represented as a string in JavaScript?random10to6th_concatToTimestamp_roundRNGOnly()returns strings instead of numbers which are not affected by precision issues.Math.round(Math.random() * Math.pow(10, 6))does not affect precision issues?Math.round(Math.random() * Math.pow(10, 6))is more likely to have collisions thanMath.random() * Math.pow(10, 6)because rounding limits the possible set of values to 10^6 possible values.Blob URLs N times. See also How would one generate a MAC address in Javascript?