为什么javascript中的`btoa`编码适用于20位数字串而不是20位数字?

Kev*_*vin 1 javascript hash encoding

考虑以下btoa输出

btoa(99999999999999999999)
"MTAwMDAwMDAwMDAwMDAwMDAwMDAw"

btoa(99999999999999999998)
"MTAwMDAwMDAwMDAwMDAwMDAwMDAw"

btoa("99999999999999999998")
"OTk5OTk5OTk5OTk5OTk5OTk5OTg="

btoa("99999999999999999999")
"OTk5OTk5OTk5OTk5OTk5OTk5OTk="
Run Code Online (Sandbox Code Playgroud)

我们看到btoa无法编码20位数的唯一哈希,int但能够编码20位数string.为什么是这样?

我最初的猜测是,既然btoa是基础,64它只能编码低于基数的东西64,但为什么它能够编码20位string呢?

而且btoa似乎不能编码int少于9223372036854775807a2^63

btoa(9223372036854775302)
"OTIyMzM3MjAzNjg1NDc3NjAwMA=="

btoa(9223372036854775303)
"OTIyMzM3MjAzNjg1NDc3NjAwMA=="
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 6

因为浮点不精确.请记住,JavaScript 在某些计算过程中暂时没有整数 ; 所有JavaScript编号都是IEEE-754双精度浮点数.99999999999999999999在IEEE-754数字中不是安全的整数值,事实上如果你这样做:

console.log(99999999999999999999);
Run Code Online (Sandbox Code Playgroud)

...你会看到的

100000000000000000000

最大安全整数(例如,不受浮点不精确影响的整数)是9007199254740991.

因为btoa接受一个字符串(当你传递一个数字,数字只是转换为字符串),只需在你的值周围加上引号:

btoa("99999999999999999999")
=> OTk5OTk5OTk5OTk5OTk5OTk5OTk=
Run Code Online (Sandbox Code Playgroud)

当然,如果值是数学计算的结果,则不能这样做.您将不得不更改计算如此大数字的任何内容,因为它们超出了数字类型的精确范围.