简易信息网

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 9|回复: 0

JS最大整数

[复制链接]

31

主题

50

帖子

203

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
203
发表于 2018-1-1 13:45:41 | 显示全部楼层 |阅读模式
JS 的整型你懂了吗?[backcolor=rgba(1, 126, 102, 0.08)]node.js

[backcolor=rgba(1, 126, 102, 0.08)]javascript

gaara 2015年03月19日发布



赞  [color=rgba(255, 255, 255, 0.2)]|   5收藏  [color=rgba(0, 0, 0, 0.0980392)]|  34
11.6k 次浏览




[size=1.75em]JS 中的最大安全整数是多少?JS 中所有的数字类型,实际存储都是通过 8 字节 double 浮点型 表示的。浮点数并不是能够精确表示范围内的所有数的, 虽然 double 浮点型的范围看上去很大: [size=0.93em]2.23x10^(-308) ~ 1.79x10^308。 可以表示的最大整数可以很大,但能够精确表示,使用算数运算的并没有这么大。
它其实连这样的简单加法也会算错:
[size=0.93em][size=1em]console.log([size=1em]0.1 [size=1em]+ [size=1em]0.2[size=1em])
[size=1em]//output: 0.30000000000000004

所以在 js 中能够安全使用的有符号 安全 大整数(注意这里是指能够安全使用,进行算数运算的范围),并不像其他语言在 64 位环境中那样是:
[size=0.93em][size=1em]2[size=1em]^[size=1em]63 [size=1em]- [size=1em]1[size=1em];[size=1em]//9223372036854775807
而是
[size=0.93em][size=1em]Math.pow([size=1em]2[size=1em], [size=1em]53[size=1em]) - [size=1em]1[size=1em]    [size=1em]// 9007199254740991
JS 的最大和最小安全值可以这样获得:
[size=0.93em][size=1em]console[size=1em].log([size=1em]Number[size=1em].MAX_SAFE_INTEGER); [size=1em]//9007199254740991
[size=1em]console[size=1em].log([size=1em]Number[size=1em].MIN_SAFE_INTEGER); [size=1em]//-9007199254740991

通过下面的例子,你会明白为什么大于这个值的运算是不安全的:
[size=0.93em][size=1em]var x = [size=1em]9223372036854775807[size=1em];
[size=1em]console.log(x === x + [size=1em]1[size=1em]);[size=1em]// output: true
[size=1em]console.log([size=1em]9223372036854775807 [size=1em]+ [size=1em]1000[size=1em]); [size=1em]//output: 9223372036854776000

这些运算都是错误的结果, 因为它们进行的都是浮点数运算会丢失精度。
[size=1.75em]为什么是这个值?double 浮点数结构如下:


  • 1 位符号位
  • 11 位指数位
  • 52 位尾数位
使用 52 位表示一个数的整数部分,那么最大可以精确表示的数应该是 [size=0.93em]2^52 - 1 才对, 就像 64 位表示整数时那样: [size=0.93em]2^63 - 1(去掉 1 位符号位)。 但其实浮点数在保存数字的时候做了规格化处理,以 10 进制为例:
[size=0.93em][size=1em]20[size=1em]*[size=1em]10[size=1em]^[size=1em]2 [size=1em]=> [size=1em]2[size=1em]*[size=1em]10[size=1em]^[size=1em]3 [size=1em]//小数点前只需要保留 1 位数
对于二进制来说, 小数点前保留一位, 规格化后始终是 [size=0.93em]1.***, 节省了 1 bit,这个 1 并不需要保存。
[size=1.75em]如何处理大整数Nodejs 越来越多的应用到后端的开发中, 不可避免的需要处理这样的溢出问题, 好在已经有很多优秀的第三方库来解决该问题:bignumbigint
[size=1.75em]大整数与数据库Mysql 能处理的各个整形范围如下
[size=0.93em][size=1em]//每种类型的第二行为无符号范围
[size=1em]TYPE         BYTE   MIN            MAX
[size=1em]TINYINT      [size=1em]1[size=1em]    [size=1em]-128[size=1em]            [size=1em]127
[size=1em]                                  [size=1em]255
[size=1em]SMALLINT    [size=1em]2[size=1em]    [size=1em]-32768[size=1em]          [size=1em]32767
[size=1em]                                  [size=1em]65535
[size=1em]MEDIUMINT    [size=1em]3[size=1em]    [size=1em]-8388608[size=1em]       [size=1em]8388607
[size=1em]                                 [size=1em]16777215
[size=1em]INT          [size=1em]4[size=1em]   [size=1em]-2147483648[size=1em]    [size=1em]2147483647
[size=1em]                               [size=1em]4294967295
[size=1em]BIGINT       [size=1em]8[size=1em] [size=1em]-9223372036854775808[size=1em]    [size=1em]9223372036854775807
[size=1em]                                       [size=1em]18446744073709551615

[size=0.93em]BIGINT 就是 64 位整数, 一旦要处理的数据量超过了 [size=0.93em]BIGINT 能存储的范围,便要考虑使用字符串保存, 坏处是数字的算数运算需要通过应用程序使用大整数库来处理,不能依赖于数据库。
注: 常常看到 BIGINT(5) 或者 INT(10), 括号里的 5 或 10 只是表示展示宽度,并不影响数的精度范围和存储字节数,需要与 VARCHAR(100)或 DECIMAL(10,2)区分开
[size=1.75em]如何处理要求精度的运算?当涉及财物类型的运算时, 位数一般不会溢出, 但精度要求回更高。数据库保存这些值时,需要使用 [size=0.93em]DECIMAL ([size=0.93em]NUMERIC 类型与之相同) 类型保存字段, 防止精度丢失。
[size=1.75em]小心位移操作前面讨论了可以使用的安全整数范围,但在做位移操作时请小心:位移操作时,会将整数截断为 32 位有符号整型。也就是说超出这个范围的位移操作将会得到错误的值。例如:


[size=0.93em][size=1em]196 [size=1em]<< [size=1em]24[size=1em];// 输出: -[size=1em]1006632960 [size=1em]正确应为: [size=1em]3288334336
位移的一些技巧可以戳 -> 这里





  今天的心情非常美丽哦!!!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|Comsenz Inc. ( 沪ICP备10006327号-1

GMT+8, 2018-1-19 15:15 , Processed in 0.047724 second(s), 21 queries .

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表