JS中的最⼤安全整数是多少?
JS 中所有的数字类型,实际存储都是通过 8 字节 double 浮点型 表⽰的。浮点数并不是能够精确表⽰范围内的所有数的, 虽然 double 浮点型的范围看上去很⼤:
2.23x10^(-308) ~ 1.79x10^308。
可以表⽰的最⼤整数可以很⼤,但能够精确表⽰,使⽤算数运算的并没有这么⼤。
它其实连这样的简单加法也会算错:
console.log(0.1 + 0.2)
//output: 0.30000000000000004
所以在 js 中能够安全使⽤的有符号 安全 ⼤整数(注意这⾥是指能够安全使⽤,进⾏算数运算的范围),并不像其他语⾔在 64 位环境中那样是:
2^63 - 1;//9223372036854775807
⽽是
Math.pow(2, 53) - 1    // 9007199254740991
JS 的最⼤和最⼩安全值可以这样获得:
console.log(Number.MAX_SAFE_INTEGER); //9007199254740991
console.log(Number.MIN_SAFE_INTEGER); //-9007199254740991
通过下⾯的例⼦,你会明⽩为什么⼤于这个值的运算是不安全的:
var x = 9223372036854775807;
console.log(x === x + 1);// output: true
console.log(9223372036854775807 + 1000); //output: 9223372036854776000
这些运算都是错误的结果, 因为它们进⾏的都是浮点数运算会丢失精度。
为什么是这个值?
double 浮点数结构如下:
1 位符号位
11 位指数位
52 位尾数位
使⽤ 52 位表⽰⼀个数的整数部分,那么最⼤可以精确表⽰的数应该是 2^52 - 1 才对, 就像 64 位表⽰整数时那样:
2^63 - 1 (去掉 1 位符号位)。
但其实浮点数在保存数字的时候做了规格化处理,以 10 进制为例:
2010^2 => 210^3 //⼩数点前只需要保留 1 位数
对于⼆进制来说, ⼩数点前保留⼀位, 规格化后始终是 1.***, 节省了 1 bit,这个 1 并不需要保存。
如何处理⼤整数
Nodejs 越来越多的应⽤到后端的开发中, 不可避免的需要处理这样的溢出问题, 好在已经有很多优秀的第三⽅库来解决该问题:bignum、bigint。
⼤整数与数据库
Mysql 能处理的各个整形范围如下
//每种类型的第⼆⾏为⽆符号范围
TYPE        BYTE  MIN            MAX
TINYINT      1    -128            127
255
SMALLINT    2    -32768          32767
65535
MEDIUMINT    3    -8388608      8388607
16777215
INT          4  -2147483648    2147483647
4294967295
BIGINT      8  -9223372036854775808    9223372036854775807
18446744073709551615
BIGINT 就是 64 位整数, ⼀旦要处理的数据量超过了 BIGINT 能存储的范围,便要考虑使⽤字符串保存, 坏处是数字的算数运算需要通过应⽤程序使⽤⼤整数库来处理,不能依赖于数据库。
注: 常常看到 BIGINT(5) 或者 INT(10), 括号⾥的 5 或 10
只是表⽰展⽰宽度,并不影响数的精度范围和存储字节数,需要与 VARCHAR(100)或 DECIMAL(10,2)区分开*
如何处理要求精度的运算?
当涉及财物类型的运算时, 位数⼀般不会溢出, 但精度要求回更⾼。数据库保存这些值时,需要使⽤ DECIMAL (NUMERIC类型与之相同) 类型保存字段, 防⽌精度丢失。
⼩⼼位移操作
前⾯讨论了可以使⽤的安全整数范围,但在做位移操作时请⼩⼼:位移操作时,会将整数截断为 32 位有符号整型。也就是说超出这个范围的位移操作将会得到错误的值。例如:
decimal是整数数据类型196 << 24;// 输出: -1006632960 正确应为: 3288334336

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。