JS 中全部的数字类型,实际存储都是经过 8 字节 double 浮点型 表示的。浮点数并非可以精确表示范围内的全部数的, 虽然 double 浮点型的范围看上去很大: 2.23x10^(-308) ~ 1.79x10^308
。 能够表示的最大整数能够很大,但可以精确表示,使用算数运算的并无这么大。javascript
它其实连这样的简单加法也会算错:html
console.log(0.1 + 0.2) //output: 0.30000000000000004
因此在 js 中可以安全使用的有符号 安全 大整数(注意这里是指可以安全使用,进行算数运算的范围),并不像其余语言在 64 位环境中那样是:java
2^63 - 1;//9223372036854775807
而是node
Math.pow(2, 53) - 1 // 9007199254740991
JS 的最大和最小安全值能够这样得到:git
console.log(Number.MAX_SAFE_INTEGER); //9007199254740991 console.log(Number.MIN_SAFE_INTEGER); //-9007199254740991
经过下面的例子,你会明白为何大于这个值的运算是不安全的:github
var x = 9223372036854775807; console.log(x === x + 1);// output: true console.log(9223372036854775807 + 1000); //output: 9223372036854776000
这些运算都是错误的结果, 由于它们进行的都是浮点数运算会丢失精度。sql
double 浮点数结构以下:数据库
使用 52 位表示一个数的整数部分,那么最大能够精确表示的数应该是 2^52 - 1
才对, 就像 64 位表示整数时那样: 2^63 - 1
(去掉 1 位符号位)。 但其实浮点数在保存数字的时候作了规格化处理,以 10 进制为例:后端
20*10^2 => 2*10^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 位有符号整型。也就是说超出这个范围的位移操做将会获得错误的值。例如:
196 << 24;// 输出: -1006632960 正确应为: 3288334336
位移的一些技巧能够戳 -> 这里
若是你有更好的关于浮点数相关学习资料, 但愿能留言推荐!