数值类型概述
整数与浮点数
在 JavaScript
内部,所有数字都是以64
位浮点数形式储存,故1
与1.0
是相同的。
1 === 1.0 // true
在转化浮点数为二进制进行存储的时候,往往存储的不是准确的值,这使得浮点数运算中往往出现问题。
0.1 + 0.2 === 0.3 // false
0.3 / 0.1 // 2.9999999999999996
(0.3 - 0.2) === (0.2 - 0.1) // false
数值精度
根据国际标准 IEEE 754,JavaScript 浮点数的64个二进制位,从最左边开始,是这样组成的。
- 第1位:符号位,0表示正数,1表示负数
- 第2位到第12位(共11位):指数部分
- 第13位到第64位(共52位):小数部分(即有效数字)
符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。
一个数在 JavaScript 内部精度最多只能到53个二进制位,这意味着,绝对值小于 253 的整数,即 -253 到 253,都可以精确表示。
Math.pow(2, 53)// 9007199254740992
Math.pow(2, 53) + 1// 9007199254740992
Math.pow(2, 53) + 2// 9007199254740994
9007199254740992111// 9007199254740992000
数值范围
根据标准,64位浮点数的指数部分的长度是11个二进制位,意味着指数部分的最大值是2047(2的11次方减1)。也就是说,64位浮点数的指数部分的值最大为2047,分出一半表示负数,则 JavaScript 能够表示的数值范围为21024到2-1023(开区间),超出这个范围的数无法表示。
如果一个数大于等于2的1024次方,那么就会发生“正向溢出”,即 JavaScript 无法表示这么大的数,这时就会返回Infinity。
如果一个数小于等于2的-1075次方(指数部分最小值-1023,再加上小数部分的52位),那么就会发生为“负向溢出”,即 JavaScript 无法表示这么小的数,这时会直接返回0。
JavaScript 浮点数陷阱及解法
数值的表示方法
- 字面形式表示
- 科学计数法表示
小数点前的数字多于21位或小数点后的零多于5个时,JavaScript 会自动将数值转为科学计数法表示。
数值的进制
- 十进制:没有前导0的数值。
- 八进制:有前缀0o或0O的数值,或者有前导0、且只用到0-7的八个阿拉伯数* 字的数值。
- 十六进制:有前缀0x或0X的数值。
- 二进制:有前缀0b或0B的数值。
特殊数值
NaN
- NaN(Not a Number)是数值类型的一个特殊值,表示"非数字"。
5 - 'x' // NaN
Math.acos(2) // NaN
Math.log(-1) // NaN
Math.sqrt(-1) // NaN
0 / 0 // NaN
-
NaN
不是独立的数据类型,它是数值类型的一个特殊值,数据类型理应为Number
。
typeof NaN // 'number'
-
NaN
不等于任何值,包括它本身
NaN === NaN // false
-
NaN
在布尔运算时被当作false
Boolean(NaN) // false
-
NaN
与任何数(包括它自己)的运算,得到的都是NaN
NaN + 32 // NaN
NaN - 32 // NaN
NaN * 32 // NaN
NaN / 32 // NaN
NaN + NaN // NaN
Infinity
-
Infinity
表示“无穷”
Math.pow(2, 1024)// Infinity
1 / 0 // Infinity
-
Infinity
有正负之分,Infinity
表示正的无穷,-Infinity
表示负的无穷。
Infinity === -Infinity // false
1 / -0 // -Infinity
-1 / -0 // Infinity
-
Infinity
大于一切数值(除了NaN
),-Infinity
小于一切数值(除了NaN
)。Infinity
与NaN
比较,总是返回false
。
Infinity > 1000 // true
-Infinity < -1000 // true
Infinity > NaN // false
-Infinity > NaN // false
Infinity < NaN // false
-Infinity < NaN // false
-
Infinity
运算规则
Infinity
的四则运算,符合无穷的数学计算规则。
5 * Infinity // Infinity
5 - Infinity // -Infinity
Infinity / 5 // Infinity
5 / Infinity // 0
0
乘以 Infinity
,返回 NaN
;0
除以 Infinity
,返回 0
;Infinity
除以 0
,返回 Infinity
。
0 * Infinity // NaN
0 / Infinity // 0
Infinity / 0 // Infinity
Infinity
加上或乘以 Infinity
,返回的还是 Infinity
。
Infinity + Infinity // Infinity
Infinity * Infinity // Infinity
Infinity
减去或除以 Infinity
,得到 NaN
。
Infinity - Infinity // NaN
Infinity / Infinity // NaN
Infinity
与 null
计算时,null
会转成 0
,等同于与 0
的计算。
null * Infinity // NaN
null / Infinity // 0
Infinity / null // Infinity
Infinity
与 undefined
计算,返回的都是 NaN
。
undefined + Infinity // NaN
undefined - Infinity // NaN
undefined * Infinity // NaN
undefined / Infinity // NaN
Infinity / undefined // NaN
与数值相关的全局方法
parseInt()
-
parseInt
方法用于将字符串转为整数。 - 如果字符串头部有空格,空格会被自动去除。
- 如果parseInt的参数不是字符串,则会先转为字符串再转换。
- 字符串转为整数的过程是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分。如果第一个字符不能转化为数字,则返回
NaN
,
parseInt('8a') // 8
parseInt('12**') // 12
parseInt('12.34') // 12
parseInt('15e2') // 15
parseInt('15px') // 15
parseInt('abc') // NaN
parseInt('.3') // NaN
parseInt('') // NaN
parseInt('+') // NaN
parseInt('+1') // 1
- parseInt的返回值只有两种可能,要么是一个十进制整数,要么是 `NaN。
- 进制问题
如果字符串以0x或0X开头,parseInt会将其按照十六进制数解析。
parseInt('0x10') // 16
如果字符串以0开头,将其按照10进制解析。
parseInt('011') // 11
parseInt
方法还可以接受第二个参数,表示被解析的值的进制,返回该值对应的十进制数。
parseInt('1000', 2) // 8
parseInt('1000', 6) // 216
parseInt('1000', 8) // 512
parseInt('1000', 10) // 1000
- 科学记数法问题
对于那些会自动转为科学计数法的数字,parseInt
会将科学计数法的表示方法视为字符串,因此导致一些奇怪的结果。
parseInt(1000000000000000000000.5) // 1
// 等同于
parseInt('1e+21') // 1
parseInt(0.0000008) // 8
// 等同于
parseInt('8e-7') // 8
parseFloat()
-
parseFloat
方法用于将一个字符串转为浮点数。 - 科学记数法问题
如果字符串符合科学计数法,则会进行相应的转换。
parseFloat('314e-2') // 3.14
parseFloat('0.0314E+2') // 3.14
-
parseFloat
方法会自动忽略前导字符和不能再继续转为浮点数的字符且不再继续往后转换。
parseFloat('\n\t3.14abc432') //3.14
- 如果参数不是字符串,或者字符串的第一个字符不能转化为浮点数,则返回NaN。
parseFloat([]) // NaN
parseFloat('FF2') // NaN
parseFloat('') // NaN
isNaN()
-
isNaN
方法可以用来判断一个值是否为NaN
。但isNaN
只对数值有效,如果传入其他值,会被先转成数值。 - 特殊的,对于空数组和只有一个数值成员的数组,
isNaN
返回false
。
isNaN([]) // false
isNaN([123]) // false
isNaN(['123']) // false
- 判断是否为
NaN
的方法
//使用 isNaN 方法同时判断数据类型。
function myIsNaN(value) {
return typeof value === 'number' && isNaN(value);
}
//利用 NaN 不等于自身的值的特点
function myIsNaN(value) {
return value !== value;
}
isFinite()
- isFinite方法返回一个布尔值,表示某个值是否为正常的数值。
isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false
isFinite(undefined) // false
isFinite(null) // true
isFinite(-1) // true
isFinite(Math.pow(2,1024)) //false