ES6精華:數值擴展

ES6爲數值增長了些常量和方法,使計算更爲簡便安全。本篇歸納了這中的精華知識。安全

1 基礎

1.1 極值

JS採用IEEE 754標準的64位雙精度格式存儲數值。
數值的精度最多可達到53個二進制位(1個隱藏位和52個有效位)。
若是數值的精度超過此限度,第54位及後面的會被丟棄。模塊化

數值的極值分爲兩種:可表示的極值和可精確計算的極值(浮點型不算)。
可表示的極值:[5e-324, 1.7976931348623157e+308]
可精確計算的極值:[1 - Math.pow(2, 53), Math.pow(2, 53) - 1]code

超過精度的數值可正確顯示,但由其計算得出的結果可能不許確。

let num = 9007199254741002;
console.log( num ); // 9007199254741002
console.log( num + 1 ); // 9007199254741004
console.log( num + 3 ); // 9007199254741004

let n1 = Math.pow(2, 53) - 1 + 1 + 1;
let n2 = Math.pow(2, 53) - 1 + 1 + 2;
console.log(n1 === n2); // true

對於整數,最多能精確顯示16個十進制位,超過會被截斷。
對於小數,最多能精確顯示小數點後16個十進制位,超過會被截斷。ip

超過的位數會被截斷。

console.log( 3.000000000000001 === 3 ); // false
console.log( 3.0000000000000001 === 3 ); // true
console.log( 0.123456789123456891 ); // 0.1234567891234569

1.2 進制

二進制:0b1000B
八進制:0o1000O0100
十六進制:0x1000X100
注意,可忽略0100格式表八進制,由於嚴格模式下不容許使用。get

進制間的轉化
使用進制的完整格式,經過toString在不一樣進制間轉化。it

console.log( (10).toString(2) ); // 1010
console.log( (0b100).toString(8) ); // 4
console.log( ('0o100').toString(16) ); // 40

使用進制的值,經過parseInt將其它進制轉換成十進制。io

console.log( parseInt(100, 2) ); // 4
console.log( parseInt(100, 8) ); // 64
console.log( parseInt('100', 16) ); // 256

使用進制的完整格式,經過Number將其它進制轉化成十進制。console

console.log( Number(0b100) ); // 4
console.log( Number('0o100') ); // 64
console.log( Number('0x100') ); // 256

2 Number

完整的API列表:地址
此模塊的方法,不會默認轉化期待爲數值類型而實際不是的參數。function

2.1 模塊化

將全局方法isFinite() & isNaN(),放到了Number模塊下。
二者惟一的差異是,全局中的方法會默認轉化非數值參數,Number模塊下的不會。class

console.log( isNaN('NaN') ); // true
- 等價於
console.log( isNaN(Number('NaN')) );

只要不是 NaN ,則爲 false 。更爲嚴格嚴謹。
console.log( Number.isNaN('NaN') ); // false

2.2 整數

增長了一些常量和方法爲安全計算服務。

isInteger()
判斷一個數值是否爲整數。非數直接爲false
在JS中,整數和浮點數的儲存方式是相同的,因此2525.0被視爲同一個值。

console.log( Number.isInteger('25') ); // false
console.log( Number.isInteger(25.0) ); // true
console.log( Number.isInteger(3.0000000000000002) ); // true

isSafeInteger()
判斷整型數值是否處於安全區間內。非整型即爲false
整型數值安全區間:[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]
判斷一個算式及其結果是否安全,須要驗證它的各個項以及結果。

isTrusty(9007199254740993, 990, 9007199254740993 - 990); // 報錯

function isTrusty(left, right, result) {
  if (Number.isSafeInteger(left)
    && Number.isSafeInteger(right)
    && Number.isSafeInteger(result)) {
    return result;
  }
  throw new RangeError('Operation cannot be trusted!');
}

2.3 偏差

JS能識別的最小精度爲Number.EPSILON,即Math.pow(2, -52)
若是偏差小於此精度,就能夠認爲這點偏差已經沒有意義,即不存在偏差了。
在實際項目中,能夠設置計算的容錯偏差,以對比兩個浮點數應不該該相同等等。

console.log( 0.1 + 0.2 ); // 0.30000000000000004
console.log( (0.1 + 0.2) === 0.3 ); // false
console.log( isEqualInErrorRange(0.1 + 0.2, 0.3) ); // true

function isEqualInErrorRange(left, right) {
  return Math.abs(left - right) < Number.EPSILON;
}

設定須要精確的位數,將浮點型轉化成整型,來較爲安全的計算浮點數。

console.log( countFloat(0.1, 0.2, '+', 14) ); // 0.3

function countFloat(a, b, sign, num) {
  let res;
  let times = Math.pow(10, num);
  let _a = Math.floor(a * times);
  let _b = Math.floor(b * times);
  
  switch (sign) {
    case '-':
      res = isTrusty(_a, _b, _a - _b);
      break;
    case '+':
      res = isTrusty(_a, _b, _a + _b);
      break;
    case '/':
      res = isTrusty(_a, _b, _a / _b);
      break;
    case '*':
      res = isTrusty(_a, _b, _a * _b);
      break;
  }
  
  return res / times;
}

3 Math

完整的API列表:地址
此模塊的方法,會默認調用Number()轉化,期待爲數值類型而實際不是的參數。 此模塊新增了些,能夠自行實現的簡易方法,直接查手冊會更有效,就不列舉了。

相關文章
相關標籤/搜索