乐趣区

数据类型-数值

1. 概述
1.1 整数和浮点数
1.2 数值精度
1.3 数值范围
2. 数值的表示法
3. 数值的进制
4. 特殊数值
4.1 正零和负零
4.2NaN
4.3Infinity
5. 与数值相关的全局方法
5.1parseInt()
5.2parseFloat()
5.3isNaN()
5.4isFinite()

1. 概述
1.1 整数和浮点数

所有数字都是以 64 位浮点数形式储存

JavaScript 语言的底层根本没有整数,所有数字都是小数

由于浮点数不是精确的值,所以涉及小数的比较和运算要特别小心。

0.1 + 0.2 === 0.3
// false

0.3 / 0.1
// 2.9999999999999996

(0.3 – 0.2) === (0.2 – 0.1)
// false

1.2 数值精度

的 64 个二进制位,从最左边开始,是这样组成的。

第 1 位:符号位,0 表示正数,1 表示负数
第 2 位到第 12 位(共 11 位):指数部分
第 13 位到第 64 位(共 52 位):小数部分(即有效数字

如果指数部分的值在 0 到 2047 之间(不含两个端点),那么有效数字的第一位默认总是 1,不保存在 64 位浮点数之中
(-1)^ 符号位 1.xx…xx 2^ 指数部分

1.3 数值范围
64 位浮点数的指数部分的长度是 11 个二进制位,意味着指数部分的最大值是 2047(2 的 11 次方减 1)

64 位浮点数的指数部分的值最大为 2047,分出一半表示负数,则 JavaScript 能够表示的数值范围为 21024 到 2 -1023(开区间),超出这个范围的数无法表示。

如果一个数大于等于 2 的 1024 次方,那么就会发生“正向溢出”,即 JavaScript 无法表示这么大的数,这时就会返回 Infinity。

Math.pow(2, 1024) // Infinity
如果一个数小于等于 2 的 -1075 次方(指数部分最小值 -1023,再加上小数部分的 52 位),那么就会发生为“负向溢出”,即 JavaScript 无法表示这么小的数,这时会直接返回 0。

Math.pow(2, -1075) // 0

var x = 0.5;

for(var i = 0; i < 25; i++) {
x = x * x;
}

x // 0
上面代码中,对 0.5 连续做 25 次平方,由于最后结果太接近 0,超出了可表示的范围,JavaScript 就直接将其转为 0。

JavaScript 提供 Number 对象的 MAX_VALUE 和 MIN_VALUE 属性,返回可以表示的具体的最大值和最小值。

Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324

2. 数值的表示法
除了 35(十进制)和 0xFF(十六进制)。

数值也可以采用科学计数法表示,下面是几个科学计数法的例子。

123e3 // 123000
123e-3 // 0.123
-3.1E+12
.1e-23
科学计数法允许字母 e 或 E 的后面,跟着一个整数,表示这个数值的指数部分

3. 数值的进制
4. 特殊数值

十进制:没有前导 0 的数值。
八进制:有前缀 0o 或 0O 的数值,或者有前导 0、且只用到 0 - 7 的八个阿拉伯数字的数值。
十六进制:有前缀 0x 或 0X 的数值。
二进制:有前缀 0b 或 0B 的数值

如果八进制、十六进制、二进制的数值里面,出现不属于该进制的数字,就会报错。

0xzz // 报错
0o88 // 报错
0b22 // 报错

有前导 0 的数值会被视为八进制,但是如果前导 0 后面有数字 8 和 9,则该数值被视为十进制。

0888 // 888
0777 // 511

4.1 正零和负零
区别就是 64 位浮点数表示法的符号位不同。它们是等价的。

-0 === +0 // true
0 === -0 // true
0 === +0 // true

几乎所有场合,正零和负零都会被当作正常的 0。

+0 // 0
-0 // 0
(-0).toString() // ‘0’
(+0).toString() // ‘0’
唯一有区别的场合是,+ 0 或 - 0 当作分母,返回的值是不相等的。

(1 / +0) === (1 / -0) // false
上面的代码之所以出现这样结果,是因为除以正零得到 +Infinity,除以负零得到 -Infinity,这两者是不相等的(关于 Infinity 详见下文)。

4.2NaN

非数字
将字符串解析成数字出错的场合。
一些数学函数的运算结果会出现 NaN。

Math.acos(2) // NaN
Math.log(-1) // NaN
Math.sqrt(-1) // NaN
0 除以 0 也会得到 NaN。

0 / 0 // NaN

NaN 不等于任何值,包括它本身。

NaN === NaN // false
数组的 indexOf 方法内部使用的是严格相等运算符,所以该方法对 NaN 不成立。

[NaN].indexOf(NaN) // -1
NaN 在布尔运算时被当作 false。

Boolean(NaN) // false
NaN 与任何数(包括它自己)的运算,得到的都是 NaN。

NaN + 32 // NaN
NaN – 32 // NaN
NaN * 32 // NaN
NaN / 32 // NaN

4.3Infinity
0 除以 0 等于 nan
其他 0 当除数 0
0 当被除数正 无穷被除为 0
0 * Infinity // NaN
1 / -0 // -Infinity
-1 / -0 // Infinity
Infinity 与 NaN 比较,总是返回 false。

Infinity > NaN // false
-Infinity > NaN // false

Infinity < NaN // false
-Infinity < NaN // false

(2)运算规则
很普通数
5 * Infinity // Infinity
5 – Infinity // -Infinity
Infinity / 5 // Infinity
5 / Infinity // 0

跟 0
0 * Infinity // NaN
0 / Infinity // 0
Infinity / 0 // Infinity
加减乘除
Infinity – Infinity // NaN
Infinity / Infinity // NaN
Infinity + Infinity // Infinity
Infinity * Infinity // Infinity

5. 与数值相关的全局方法
5.1parseInt(字符串,进制数 2 -36)
parseInt 方法用于将字符串转为整数
返回 nan 或者十进值

回先 string 转为字符串再转化
有多少转多少
1. 如果字符串头部有空格,空格会被自动去除。

parseInt(‘ 81’) // 81

2. 如果字符串以 0x 或 0X 开头,parseInt 会将其按照十六进制数解析。

parseInt(‘0x10’) // 16
如果字符串以 0 开头,将其按照 10 进制解析。

parseInt(‘011’) // 11
对于那些会自动转为科学计数法的数字,parseInt 会将科学计数法的表示方法视为字符串,因此导致一些奇怪的结果。

parseInt(1000000000000000000000.5) // 1
// 等同于
parseInt(‘1e+21’) // 1

parseInt(0.0000008) // 8
// 等同于
parseInt(‘8e-7’) // 8

(2)进制转换

如果第二个参数不是数值,会被自动转为一个整数。这个整数只有在 2 到 36 之间,才能得到有意义的结果,超出这个范围,则返回 NaN。如果第二个参数是 0、undefined 和 null,则直接忽略。

parseInt(’10’, 37) // NaN
parseInt(’10’, 1) // NaN
parseInt(’10’, 0) // 10
parseInt(’10’, null) // 10
parseInt(’10’, undefined) // 10

如果字符串包含对于指定进制无意义的字符,则从最高位开始,只返回可以转换的数值。如果最高位无法转换,则直接返回 NaN。

parseInt(‘1546’, 2) // 1
parseInt(‘546’, 2) // NaN

前面说过,如果 parseInt 的第一个参数不是字符串,会被先转为字符串。这会导致一些令人意外的结果。

parseInt(0x11, 36) // 43
parseInt(0x11, 2) // 1

// 等同于
parseInt(String(0x11), 36)
parseInt(String(0x11), 2)

// 等同于
parseInt(’17’, 36)
parseInt(’17’, 2)
上面代码中,十六进制的 0x11 会被先转为十进制的 17,再转为字符串。然后,再用 36 进制或二进制解读字符串 17,最后返回结果 43 和 1。

这种处理方式,对于八进制的前缀 0,尤其需要注意。

parseInt(011, 2) // NaN

// 等同于
parseInt(String(011), 2)

// 等同于
parseInt(String(9), 2)
上面代码中,第一行的 011 会被先转为字符串 9,因为 9 不是二进制的有效字符,所以返回 NaN。如果直接计算 parseInt(‘011’, 2),011 则是会被当作二进制处理,返回 3。
5.2parseFloat()

parseFloat 方法用于将一个字符串转为浮点数

1. 多少符合转多少
2. 如果字符串符合科学计数法,则会进行相应的转换。

parseFloat(‘314e-2’) // 3.14
parseFloat(‘0.0314E+2’) // 3.14
3. 如果参数不是字符串,或者字符串的第一个字符不能转化为浮点数,则返回 NaN 空字符串也是 nan
这些特点使得 parseFloat 的转换结果不同于 Number 函数。

parseFloat(true) // NaN
Number(true) // 1

parseFloat(null) // NaN
Number(null) // 0

parseFloat(”) // NaN
Number(”) // 0

parseFloat(‘123.45#’) // 123.45
Number(‘123.45#’) // NaN

5.3isNaN()
Nan===nan 假
isNaN(NaN) // true
先 number()再判断

真 字符串 对象 undefined
假 空数组 只有一个数值的数组
isNaN([]) // false
isNaN([123]) // false
isNaN([‘123’]) // false

因此,使用 isNaN 之前,最好判断一下数据类型。

function myIsNaN(value) {
return typeof value === ‘number’ && isNaN(value);
}
判断 NaN 更可靠的方法是,利用 NaN 为唯一不等于自身的值的这个特点,进行判断。

function myIsNaN(value) {
return value !== value;
}

5.4isFinite()

真假,是否正常值
除了 Infinity、-Infinity、NaN 和 undefined 这几个值会返回 false

退出移动版