如何在纯 JavaScript(不是 Node.js)的范围内生成随机 BigInt?
How to generate random BigInt within a range in plain JavaScript (not Node.js)?
JavaScript中的基本随机数在特定范围内有这个很好的问题:
Generating random whole numbers in JavaScript in a specific range?
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
如何在普通 JavaScript 中使用 BigInt 做同样的事情(即不使用 Node.js 或使用 crypto.randomBytes
)?跨环境工作的东西(支持 BigInt)?
(大声思考...) 您不能只更改要附加 n
的公式中的数字以使它们成为 BigInt,因为 Math.random()
returns 一个非 BigInt。例如Math.random()
returns0.5427862726372646
,即16位小数。但是如果我有一个类似于 41223334444555556666667777777888888889999999997n
的 BigInt,那是一个 47 位数字,所以乘以 0.5427862726372646 * (10**46)
得到 5.4278627263726465e+45
。将其包装在 BigInt
中,您会得到 BigInt(0.5427862726372646 * (10**46))
等于 5427862726372646467145376115182187925303459840n
。嗯...这是解决方案吗?
41223334444555556666667777777888888889999999997n
5427862726372646467145376115182187925303459840n
结果如何?如果那是我刚才偶然发现的解决方案,试图问这个问题。您能否仔细检查并确认这是正确的,并解释一下当传递给 BigInt
构造函数时,常规 JavaScript 数字(具有 e+45
表示)如何产生看似准确详细的 BigInt
值?那我试试看吧
BigInt(Math.random() * (10 ** 45))
// => 329069627052628509799118993772820125779492864n
嗯。没看懂,Math.random()
原来只有16位?
const rand = Math.random()
// => 0.7894008119121056
BigInt(rand * (10 ** 45))
// => 789400811912105533187528403423793891092987904n
这没有意义,我本以为:
789400811912105600000000000000000000000000000
也就是说,0.7894008119121056 移动了 45 位小数。
不确定为什么会这样,是不是只在 Chrome 中?
最后一个测试:
console.log('10 ** 35 <=> 10 ** 45')
console.log(rint(10 ** 35, 10 ** 45).toString())
console.log('10 ** 35 <=> 10 ** 45')
console.log(rint(10 ** 35, 10 ** 45).toString())
console.log('10 ** 20 <=> 10 ** 40')
console.log(rint(10 ** 20, 10 ** 40).toString())
console.log('10 ** 20 <=> 10 ** 40')
console.log(rint(10 ** 20, 10 ** 40).toString())
function rint(min, max) {
return BigInt(Math.random() * max - min + 1) + BigInt(min)
}
我得到例如:
10 ** 35 <=> 10 ** 45 485253180777775593983353876860021068179439616n
10 ** 35 <=> 10 ** 45 178233587725359997576391063983941630941986816n
10 ** 20 <=> 10 ** 40 8245114695932740733462636549119006474240n
10 ** 20 <=> 10 ** 40 7214182941774644957099293094661617352704n
那么这是一个正确的实现吗? 那么你将如何实现它以获取从 0 到任意大的 BigInt 的随机整数?
JavaScript 数字始终按照国际 IEEE 754 标准存储为双精度浮点数。
此格式以 64 位存储数字(其中数字(分数)存储在位 0 到 51 中,指数存储在位 52 到 62 中,符号存储在位 63 中)。
Math.random()
returns 只有正数,因此符号位无关紧要。这意味着 Math.random()
不能产生更多 2 ** 63
不同的值,实际上它小于那个,因为 Math.random()
returns 只能产生 0 到 1 之间的值(这意味着取决于实现 none 或并非所有 11 个指数位都被使用)。当您的范围大于该范围时,Math.random()
将无法生成该范围内的每个数字。在限制范围内,您的方法应该有效。
JavaScript中的基本随机数在特定范围内有这个很好的问题:
Generating random whole numbers in JavaScript in a specific range?
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
如何在普通 JavaScript 中使用 BigInt 做同样的事情(即不使用 Node.js 或使用 crypto.randomBytes
)?跨环境工作的东西(支持 BigInt)?
(大声思考...) 您不能只更改要附加 n
的公式中的数字以使它们成为 BigInt,因为 Math.random()
returns 一个非 BigInt。例如Math.random()
returns0.5427862726372646
,即16位小数。但是如果我有一个类似于 41223334444555556666667777777888888889999999997n
的 BigInt,那是一个 47 位数字,所以乘以 0.5427862726372646 * (10**46)
得到 5.4278627263726465e+45
。将其包装在 BigInt
中,您会得到 BigInt(0.5427862726372646 * (10**46))
等于 5427862726372646467145376115182187925303459840n
。嗯...这是解决方案吗?
41223334444555556666667777777888888889999999997n
5427862726372646467145376115182187925303459840n
结果如何?如果那是我刚才偶然发现的解决方案,试图问这个问题。您能否仔细检查并确认这是正确的,并解释一下当传递给 BigInt
构造函数时,常规 JavaScript 数字(具有 e+45
表示)如何产生看似准确详细的 BigInt
值?那我试试看吧
BigInt(Math.random() * (10 ** 45))
// => 329069627052628509799118993772820125779492864n
嗯。没看懂,Math.random()
原来只有16位?
const rand = Math.random()
// => 0.7894008119121056
BigInt(rand * (10 ** 45))
// => 789400811912105533187528403423793891092987904n
这没有意义,我本以为:
789400811912105600000000000000000000000000000
也就是说,0.7894008119121056 移动了 45 位小数。
不确定为什么会这样,是不是只在 Chrome 中?
最后一个测试:
console.log('10 ** 35 <=> 10 ** 45')
console.log(rint(10 ** 35, 10 ** 45).toString())
console.log('10 ** 35 <=> 10 ** 45')
console.log(rint(10 ** 35, 10 ** 45).toString())
console.log('10 ** 20 <=> 10 ** 40')
console.log(rint(10 ** 20, 10 ** 40).toString())
console.log('10 ** 20 <=> 10 ** 40')
console.log(rint(10 ** 20, 10 ** 40).toString())
function rint(min, max) {
return BigInt(Math.random() * max - min + 1) + BigInt(min)
}
我得到例如:
10 ** 35 <=> 10 ** 45 485253180777775593983353876860021068179439616n
10 ** 35 <=> 10 ** 45 178233587725359997576391063983941630941986816n
10 ** 20 <=> 10 ** 40 8245114695932740733462636549119006474240n
10 ** 20 <=> 10 ** 40 7214182941774644957099293094661617352704n
那么这是一个正确的实现吗? 那么你将如何实现它以获取从 0 到任意大的 BigInt 的随机整数?
JavaScript 数字始终按照国际 IEEE 754 标准存储为双精度浮点数。
此格式以 64 位存储数字(其中数字(分数)存储在位 0 到 51 中,指数存储在位 52 到 62 中,符号存储在位 63 中)。
Math.random()
returns 只有正数,因此符号位无关紧要。这意味着 Math.random()
不能产生更多 2 ** 63
不同的值,实际上它小于那个,因为 Math.random()
returns 只能产生 0 到 1 之间的值(这意味着取决于实现 none 或并非所有 11 个指数位都被使用)。当您的范围大于该范围时,Math.random()
将无法生成该范围内的每个数字。在限制范围内,您的方法应该有效。