js你不知的那些基础问题-数值

1 整数和浮点数

JavaScript 语言的底层根本没有整数,所有数字都是小数(64位浮点数)。容易造成混淆的是,

某些运算只有整数才能完成,此时 JavaScript 会自动把64位浮点数,转成32位整数,然后再进行运算。

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

0.1 + 0.2 === 0.3
// false

0.3 / 0.1
// 2.9999999999999996

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

 2 数值精度

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

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

   符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。

JavaScript 提供的有效数字最长53二进制位

由于2的53次方是一个16位的十进制数值,所以简单的法则就是,JavaScript 对15位的十进制数都可以精确处理。

(-1)^符号位 * 1.xx...xx * 2^指数部分

3 数值范围  

  位浮点数的指数部分的值最大为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

  以下两种情况,JavaScript 会自动将数值转为科学计数法表示,其他情况都采用字面形式直接表示。

   (1)小数点前的数字多于21位。

1234567890123456789012
// 1.2345678901234568e+21

  (2)小数点后的零多于5个。

// 小数点后紧跟5个以上的零,
// 就自动转为科学计数法
0.0000003 // 3e-7

4 特殊数值

4.1 正负零

  JavaScript 内部实际上存在2个0:一个是+0,一个是-0

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

   唯一有区别的场合是,+0-0当作分母,返回的值是不相等的

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

4.2 NaN  

   (1)含义

  NaN是 JavaScript 的特殊值,表示“非数字”(Not a Number),

  主要出现在将字符串解析成数字出错的场合。

  0除以0也会得到NaN

0 / 0 // NaN

  需要注意的是,NaN不是独立的数据类型,而是一个特殊数值,

  它的数据类型依然属于Number,使用typeof运算符可以看得很清楚

typeof NaN // 'number'

  (2)运算规则

   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.3 Infinity

(1)含义

Infinity表示“无穷”,用来表示两种场景。

一种是一个正的数值太大,或一个负的数值太小,无法表示;

另一种是非0数值除以0,得到Infinity

// 场景一
Math.pow(2, 1024)
// Infinity

// 场景二
0 / 0 // NaN
1 / 0 // Infinity

  由于数值正向溢出(overflow)、负向溢出(underflow)和被0除,

  JavaScript 都不报错,所以单纯的数学运算几乎没有可能抛出错误。

  Infinity大于一切数值(除了NaN),-Infinity小于一切数值(除了NaN)。

Infinity > 1000 // true
-Infinity < -1000 // true

  InfinityNaN比较,总是返回false

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

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

  0乘以Infinity,返回NaN;0除以Infinity,返回0Infinity除以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

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

5.1 parseInt()

   (1)基本用法

  如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN

parseInt('abc') // NaN
parseInt('.3') // NaN
parseInt('') // NaN
parseInt('+') // NaN
parseInt('+1') // 1

  所以,parseInt的返回值只有两种可能,要么是一个十进制整数,要么是NaN

     对于那些会自动转为科学计数法的数字,parseInt会将科学计数法的表示方法视为字符串,

  因此导致一些奇怪的结果。

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

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

  (2)进制转换

 parseInt方法还可以接受第二个参数(2到36之间),表示被解析的值的进制,

返回该值对应的十进制数。默认情况下,parseInt的第二个参数为10,即默认是十进制转十进制。

parseInt('1000') // 1000
// 等同于
parseInt('1000', 10) // 1000

  如果第二个参数不是数值,会被自动转为一个整数。

  这个整数只有在2到36之间,才能得到有意义的结果,超出这个范围,则返回NaN

  如果第二个参数是0undefinednull,则直接忽略。

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

  前面说过,如果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,最后返回结果431

5.2 parseFloat()

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

parseFloat('314e-2') // 3.14
parseFloat('0.0314E+2') // 3.14

  parseFloat方法会自动过滤字符串前导的空格。

parseFloat('\t\v\r12.34\n ') // 12.34

  如果参数不是字符串,或者字符串的第一个字符不能转化为浮点数,则返回NaN

parseFloat([]) // NaN
parseFloat('FF2') // NaN
parseFloat('') // 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.3 isNaN()

  isNaN方法可以用来判断一个值是否为NaN

isNaN(NaN) // true
isNaN(123) // false

  但是,isNaN只对数值有效,如果传入其他值,会被先转成数值。

  比如,传入字符串的时候,字符串会被先转成NaN,所以最后返回true,这一点要特别引起注意。

  也就是说,isNaNtrue的值,有可能不是NaN,而是一个字符串。

isNaN('Hello') // true
// 相当于
isNaN(Number('Hello')) // true

  出于同样的原因,对于对象和数组,isNaN也返回true

isNaN({}) // true
// 等同于
isNaN(Number({})) // true

isNaN(['xzy']) // true
// 等同于
isNaN(Number(['xzy'])) // true

  但是,对于空数组和只有一个数值成员的数组,isNaN返回false

isNaN([]) // false
isNaN([123]) // false
isNaN(['123']) // false

5.4 isFinite()

  isFinite方法返回一个布尔值,表示某个值是否为正常的数值。

isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false
isFinite(undefined) // false
isFinite(null) // true
isFinite(-1) // true

  除了Infinity-InfinityNaNundefined这几个值会返回false

  isFinite对于其他的数值都会返回true

 

文章内容转自 阮一峰老师 JavaScript教程 https://wangdoc.com/javascript/index.html

posted @ 2019-08-04 20:26  WernerWu  阅读(286)  评论(0编辑  收藏  举报