Hex

Updated: 2019-01-01

入门

我们通常用的是十进制,而计算机内部都是二进制;八进制和十六进制由于可以方便的表达 3 或 4 个二进制位,所以在程序中也很常见。

例如在 Javascript 中,十六进制的0x100可以被轻松转换成二进制的100000000或十进制的256

> 0x100.toString(2)
'100000000'
> 0x100.toString(10)
'256'

坑!

2017 年的一则 Twitter:https://twitter.com/a_ferron/status/892350579162439681

由于忘了在十六进制的地址字符串上加引号,输入的参数变成了一个 Javascript 的一个十六进制数。结果?损失了一百四十万美元。

进阶

究其原因,Javascript 并没有区分整数和浮点数,数字的类型只有一个,叫number

> typeof 100
'number'
> typeof 0.01
'number'

number是个 IEEE 754 标准的 64 位double,其中 1 位是符号(sign),11 位是指数(exponent),剩下 52 位是分数(fraction)。它所能精确表达的整数是2 ** 53 - 1 = 9007199254740991

> Number.MAX_SAFE_INTEGER
9007199254740991
> Number.MIN_SAFE_INTEGER
-9007199254740991

所以当你尝试创建很大的整数的时候,结果可能并不是你想要的

> 999999999999999
999999999999999
> 9999999999999999
10000000000000000

回到这个一百四十万美元的问题,原本的十六进制地址,被当成了数字,被 Javascript 一转换,精度就被丢掉了

> 0x3e4b00b607d09811b0fa61cf636a6460861939f.toString(16)
'3e4b00b607d0980000000000000000000000000'