Javascript Number 类型详解
数值类型是js七大数据类型之一,js七大数据类型包括:数字,字符串,布尔,null, undefined,object, symbol
一:平时工作中数字类型主要运用:
- 数值的各种格式显示,比如保留几位小数,指数格式显示,本地格式显示
- 数值的各种计算,比如 加减乘除,求余,以及其他Math函数包含的各种数值计算的使用
二:JS 数值类型的存储方式?
js中数值是使用64位浮点数形式储存,遵循IEEE-754双精度标准存储,
下面是64位存储示意图:
其中
- sign 代表符号位,确定是正数还是负数
- exponent 总共11位,代表数字的指数位数和方向
- significand 总共52位 代表双精度的小数部分的数值
1.sign位置
决定正数还是负数,sign位为1代表负数
2.exponent 代表指数移动的位数:
exponent规定范围00000000001-01111111111[1-1023]是左移动(负指数),10000000001-11111111110[1025-2046]代表右移动(正指数)
举例说明:(数值的转换在计算机里都是通过2进制来换算)
比如 15 这个数字, 转换为二进制为1111
换算成指数表示法就是 1.111 * 2^3 相当于1.111右移动三位,所以指数移动位置应该存 正3
电脑是怎么从绿色的部分算出3的呢?
观察绿色的位置为10000000010(1026)
减去左移需要表示的最大数 01111111111(1023) 等于需要右移3位
10000000010(1026) - 01111111110(1023) = 11(3)
3.significand
存储小数位的数据
刚刚上面的例子 15 转换为浮点指数表示法 为 1.111 右移3位,所以小数部分就是111
所以在红色区域,为111
三:Number.MAX_VALUE 和 MAX_SAFE_INTEGER 的区别
MAX_VALUE 和 MAX_SAFE_INTEGER 是Number的两个静态属性
数值大小不同
MAX_VALUE: 1.7976931348623157e+308
MAX_SAFE_INTEGER: 9007199254740991
MAX_VALUE 是js能表达的最大的值
MAX_SAFE_INTEGER 是js能表达的最大的不丢失精度的值
我们来观察两者的存储情况
MAX_VALUE
可以看到正指数和小数都已经打满了
MAX_SAFE_INTEGER
可以看到小数部分都打满了,指数位置为 10000110011(1075)
减去 1023 ,得到的正指数为52,52后移的位数正好和小数significand的位数一样长,这样右移后不丢失任何一个小数。
所以,我们在处理精度问题的时候,为了不丢失精度,尽量使用小于MAX_SAFE_INTEGER
四:Infinity 和 -Infinity
这两个是window下的两个属性
他们对应Number里的静态属性分别为 Number.POSITIVE_INFINITY 和 Number.NEGATIVE_INFINITY
代表正无穷和负无穷。
无穷的计算规则:
- 无穷比任何有限的数字都大
- Infinity 和任何数进行加减乘除结果还是Infinity
Infinity+Infinity = Infinity
Infinity + 1 = Infinity
Infinity * Infinity = Infinity
Infinity / 2=Infinity
Infinity - 2 = Infinity - 例外:Infinity 除以或者加上Infinity 变为NaN
Infinity/Infinity=NaN
Infinity-Infinity=NaN - Infinity 和其他数字求余的时候也是NaN
Infinity%Infinity=NaN - 数字除以无穷等于0
10/Infinity = 0 - 数字除以0等于无穷
2/0 = Infinity
很多人好奇Infinity是怎么存储的
可以看到指数位打满11111111111(2047) ,超过了正指数的范围,(1025-2046),小数位全部为0
sign为如果设置为负数,则代表负无穷
五:NaN
NaN是数值里一个比较特殊的东西,
typeof NaN === ‘number’
我们可以通过Number.isNaN来判断是否是NaN
NaN的运算规则:
NaN和任何数字进行加减乘除余等运算都是NaN
NaN+1=NaN
NaN*1=NaN
NaN/1=NaN
NaN-1=NaN
0/0=NaN
Infinity*0=NaN
NaN ==NaN. =》 false
NaN在内存中是如何存储的呢?
观察下指数位全部打满,小数位第一位为1,符号为为0
六:Number.MAX_VALUE 和Number.Infinity 之间还差多少数字呢?
观察上面关于两者的存储图并参考MAX_VALUE的计算公式:
然后INFINITY套用这个公式将53变成54,
减下来的结果等于2的970次方,因为精度有限,所以很多该数值附近的数字会被约等于这个值,所以我们可以认为他们的值相差差不多就是2的970次方
七:为啥0.1+0.2!=0.3
实际结果:
按照上面的知识来分析:
0.2 转换成2进制
小数位达到了54位(其实更多,应该是无限循环),超过了52位,所以后面的两位小数会被丢弃
0.1转换为2进制
所以相加之后可能由于省略产生了进入可统计范围内的偏差。
八:其他的API内容
-
Number.EPSILON
js可识别的最小精度值,比这个再小的误差可以认为忽略不计。
比如如果 0.1+0.2的值减去0.3算出来的误差如果小于Number.EPSILON,我们可以认为0.1+0.2就是等于0.3的 -
MAX_SAFE_INTEGER
最大的安全的精度不会丢失的值 -
MAX_VALUE
最大值,超过他 就是 POSITIVE_INFINITY -
MIN_SAFE_INTEGER
最小的安全的精度不会丢失的值 -
MIN_VALUE
最小指,比他小就是NEGATIVE_INFINITY -
NaN
非数的表达方式 -
NEGATIVE_INFINITY
负无穷 -
POSITIVE_INFINITY
正无穷 -
prototype
构造函数的原型
静态方式:
- isNaN
判断是否是NaN - isFinite
判断是否是有穷的数字 - isInteger
是否是整数 - IsSafeInteger
是否是安全整数 - parseFloat
转换为浮点型数据 - parseInt
转换为整形
实例方法:
- constructor
构造函数 - toExponential
将数字转换为指数表达方式,参数num代表指数的小数位数 - toFixed
将数字显示转换为带小数的展示方式,参数为小数的个数 - toLocaleString
var a =12 ; a.toLocaleString(‘zh-Hans-CN’,{style:‘currency’, currency: 'CNY’})
"¥12.00”
转换成本地语系的字符串 - toPrecision
转换为指数的最小位数的用法,参数num
转化后的 小数点前的数字个数 和小数点后面的数字个数加起来等于num
- toString
转化为字符串 - valueOf
获取数字对象的字面值