I need to generate 26 digit numbers with Math.random, but when I use this:
Math.floor(Math.random() * 100000000000000000000000000) + 900000000000000000000000000
I gets 9.544695043285823e+26
I need to generate 26 digit numbers with Math.random, but when I use this:
Math.floor(Math.random() * 100000000000000000000000000) + 900000000000000000000000000
I gets 9.544695043285823e+26
-
Remember, such large numbers, if represented as numbers rather than strings, will not be accurate to the integer (check out
MAX_SAFE_INTEGER
) – CertainPerformance Commented Dec 22, 2018 at 8:48 -
Exactly what seems to be the problem?
9.544695043285823e+26
is a darn big number with actually 27 digits, ase+26
means that you should move the decimal separator 26 places to the right. – Chri.s Commented Dec 22, 2018 at 8:57 - you can use a library like BigInteger.js to generate random big integers (as strings) in any base and with any number of digits (up to cpu memory limit of course) – Nikos M. Commented Dec 22, 2018 at 10:53
3 Answers
Reset to default 6Modern browsers support BigInt
and bigint
primitive type and we can bine it with a random generated array containing 8 bytes (the sizeof bigint
is 8 bytes (64 bits)).
1. Generating Random BigInt
Performance Wise
We can generate a random hex string of 16 characters length and apply it directly to BigInt
:
const hexString = Array(16)
.fill()
.map(() => Math.round(Math.random() * 0xF).toString(16))
.join('');
const randomBigInt = BigInt(`0x${hexString}`);
// randomBigInt will contain a random Bigint
document.querySelector('#generate').addEventListener('click', () => {
const output = [];
let lines = 10;
do {
const hexString = Array(16)
.fill()
.map(() => Math.round(Math.random() * 0xF).toString(16))
.join('');
const number = BigInt(`0x${hexString}`);
output.push(`${
number.toString().padStart(24)
} : 0x${
hexString.padStart(16, '0')
}`);
} while (--lines > 0);
document.querySelector('#numbers').textContent = output.join('\n');
});
<button id="generate">Generate</button>
<pre id="numbers"><pre>
2. Generating Random BigInt
from random bytes array
If we want to use Uint8Array
or if we want more control over the bits manipulation, we can bine Array.prototype.fill
with Array.prototype.map
to generate an array containing 8 random byte number values (beware this is around 50% slower than the above method):
const randomBytes = Array(8)
.fill()
.map(() => Math.round(Math.random() * 0xFF));
// randomBytes will contain something similar to this:
// [129, 59, 98, 222, 20, 7, 196, 244]
Then we use Array.prototype.reduce
to initialize a BigInt
of zero value and left shift each randum byte value its position X 8 bits and applying bitwise or to the current value of each reduce
iteration:
const randomBigInt = randomBytes
.reduce((n, c, i) => n | BigInt(c) << BigInt(i) * 8n, 0n);
// randomBigInt will contain a random Bigint
Working example generating 10 random BigInt
values
document.querySelector('#generate').addEventListener('click', () => {
const output = [];
let lines = 10;
do {
const number = Array(8)
.fill()
.map(() => Math.round(Math.random() * 0xFF))
.reduce((n, c, i) => n | BigInt(c) << BigInt(i) * 8n, 0n);
output.push(`${
number.toString().padStart(24)
} : 0x${
number.toString(16).padStart(16, '0')
}`);
} while (--lines > 0);
document.querySelector('#numbers').textContent = output.join('\n');
});
<button id="generate">Generate</button>
<pre id="numbers"><pre>
Floating point numbers in JavaScript (and a lot of other languages) can contain only about 15.955 digits without losing precision. For bigger numbers you can look into JS libraries, or concatenate few numbers as strings. For example:
console.log( Math.random().toString().slice(2, 15) + Math.random().toString().slice(2, 15) )
If I use a 6 decillion LG about 72.9 million out of 300 but when I switch to 10 centillion it es like this 10 ^ 999 - 99999 + 26 just like how 9 - 9 - 9 - 9 - googolplex is equal to 0 googolplex