数值

290 阅读6分钟

1.概述

1.1整数和浮点数

JavaScript内部所有数字以64位浮点数形式储存,整数也如此,所以1和1.0是相同的一个数。 也就是说,JavaScript语言底层没有整数,所有数字都是小数(64位浮点数),整数运算时,JavaScript会自动将64位浮点数转为32位整数,再进行运算。 浮点数不是精确的值,所以涉及小数的比较和运算要特别小心。

1.2数值精度

根据国际标准IEEE754,JavaScript浮点数的64个二进制位是这样组成:

  • 第一位:符号位,0表示正数,1表示负数
  • 第二位到第十二位(共11位):指数部分
  • 第十三位到第六十四位(共52位):小数部分(即有效数字) 符号位决定一个数的正负,指数部分决定数值大小,小数部分决定数值精度。JavaScript提供的有效数字最长为53个二进制位。意味着绝对值小于2的53次方的整数,即-2^53到2^53都可以精确表示。简单的法则是,JavaScript对15位的十进制数都可以精确处理。
(-1)^符号位 * 1.xx...xx * 2^指数部分

上面公式是正常情况下,一个数在JavaScript内部实际的表示形式。

1.3数值范围

64位浮点数的指数部分长度是11个二进制位,意味着指数部分的最大值是2047(2^11-1)。JavaScript能够表示的数值范围为2^1024到2^-1024(开区间),超出这个范围的数无法表示。

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

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

2.数值的表示法

JavaScript的数值有多种表示方法,可以用字面形式直接表示,比如35(十进制)和0xFF(十六进制);也可以用科学计数法表示,比如5e-324。 两种情况JavaScript会自动将数值转为科学记数法表示,其他情况采用字面形式直接表示:

  • 小数点前的数字多于21位
  • 小数点后的零多于5个

3.数值的进制

使用字面量(literal)直接表示一个数值时,JavaScript对整数提供四种进制的表示方法:十进制、十六进制、八进制、二进制。 默认情况下,JavaScript内部会自动将八进制、十六进制、二进制转为十进制。

4.特殊数值

JavaScript提供几个特殊的数值

4.1正零和负零

JavaScript内部存在2个0:+0和-0,区别是64位浮点数表示法的符号位不同,但它们是等价的。

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

几乎所有场合,正零和负零都会被当作正常的0,唯一有区别的场合是,+0或-0当作分母,返回的值不相等。

(1 / +0) === (1 / -0) // false

4.2NaN

NaN是JavaScript的特殊值,表示非数字(Not a Number),主要出现在将字符串解析成数字出错的场合。NaN不是独立的数据类型,是一个特殊数值,数据类型依然属于Number。

  • NaN不等于任何值,包括它本身
  • 数组的indexOf方法内部使用严格相等运算符,所以该方法对NaN不成立
  • NaN在布尔运算时被当做false
  • NaN与任何数(包括它自己)的运算,得到的都是NaN

4.3Infinity

Infinity表示无穷,用来表示两种场景。一种是正数值太大,或一个负数值太小,无法表示;另一种是非0数值除以0,得到Infinity。(NaN除以0得到NaN)

  • Infinity表示正无穷,-Infinity表示负无穷
  • 单纯的数学运算几乎没有可能抛出错误
  • Infinity大于一切数值(除了NaN),-Infinity小于一切数值(除了NaN)
  • Infinity与NaN比较,总是返回NaN Infinity的运算规则:
  • Infinity的四则运算,符合无穷的数学计算规则
  • 0乘以Infinity,返回NaN
  • Infinity减去或除以Infinity,得到NaN
  • Infinity与null计算时,null会转成0,等同于与0的计算
  • Infinity与undefined计算,返回的都是NaN

5.与数值相关的全局方法

5.1parseInt()

  • parseInt()方法用于将字符串转为整数。
  • 如果字符串头部有空格,空格会被自动去除
  • 如果parseInt参数不是字符串,则会先转为字符串再转换
  • 字符串转为整数,是一个个字符串依次转换,若遇到不能转为数字的字符,就不再进行下去,返回已转好的部分
  • 如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN
  • 对于会自动转为科学计数法的数字,parseInt会将科学计数法的表示方法视为字符串,返回整数 因此,parseInt的返回值只有两种可能,要么是一个十进制整数,要么是NaN。
parseInt('1000', 2) // 8
parseInt('1000', 6) // 216
parseInt('1000', 8) // 512

parseInt方法接受第二个参数(2-36之间),表示被解析的值的进制,返回该值对应的十进制数。

  • 默认情况下,第二个参数为10
  • 若第二个参数超出2-36的范围,返回NaN,若参数是0、undefined和null,则直接忽略
  • 若字符串包含对于指定进制无意义的字符,则从最高位开始,只返回可以转换的数值,若最高位无法转换,则返回NaN
  • parseInt第一个参数不是字符串,会被先转为字符串,从而导致一些令人意外的结果

5.2parseFloat()

  • parseFloat()方法用于将一个字符串转为浮点数
  • 如果字符串符合科学计数法,则会进行相应的转换
  • 若字符串包含不能转为浮点数的字符,则不再进行往后转换,返回已经转好的部分
  • parseFloat()方法会自动过滤字符串前导空格
  • 若参数不是字符串或字符串第一个字符不能转为浮点数,则返回NaN(parseFloat会将空字符串转为NaN) 这些特点使得parseFloat()的转换结果不同与Number函数。

5.3isNaN()

  • isNaN()方法可以用来判断一个值是否为NaN
  • isNaN()只对数值有效,如果传入其他值,会被先转成数值。比如字符串会被先转成NaN,最后返回true,因此isNaN为true的值,有可能不是NaN,而是一个字符串
  • 出于同样原因,对于对象和数组,isNaN()返回true
  • 但是对于空数组和只有一个数值成员的数组,isNaN()返回false
  • 因此使用isNaN()之前,要判断以下数据类型,更可靠的方法是,利用NaN为唯一且不等于自身这个特点,进行判断

5.4 isFinite()

  • isFinite()方法返回一个布尔值,表示某个值是否为正常的数值
  • 除了Infinity/-Infinity/NaN/undefined这四个值会返回false,其他数值都返回true