1. 程式人生 > 其它 >關於Js中數字型別大於2^53(2的53次方)導致精度丟失問題及解決方案

關於Js中數字型別大於2^53(2的53次方)導致精度丟失問題及解決方案

技術標籤:JSjavascript

最近平臺接結構,通過版本號+機構號判斷跳轉相應的頁面,於是乎踩坑了.....

一番搜尋後發現,強制裝換string型別用 ‘===’ 比對會返回false,原因移步:JS字串比較區別

1. 關於js字串比較:”== “ “===”,列:

Var a=”abc”;

Var b=”abc”;

Var c=new String(“abc”);

Var d=new String(“abc”);

(1) a=== b => true,沒有建立實列物件,應該是指向預設建立的物件,只要值相同都會指向同樣物件

(2)a === c =>false,c建立了一個新的物件,並指向這個物件,用”===”對比結果為false(同理,a,b與d用”===”都為false)

(3)c === d =>false,原因與2相同,c,d兩個引用指向的物件不是同一個,都是兩個新建的

2. 雙等號 ==:

(1)如果兩個值型別相同,再進行三個等號(===)的比較

(2)如果兩個值型別不同,也有可能相等,需根據以下規則進行型別轉換在比較:

  1)如果一個是null,一個是undefined,那麼相等

  2)如果一個是字串,一個是數值,把字串轉換成數值之後再進行比較

3. 三等號 ===:

 (1)如果型別不同,就一定不相等

 (2)如果兩個都是數值,並且是同一個值,那麼相等;如果其中至少一個是NaN,那麼不相等。(判斷一個值是否是NaN,只能使用isNaN( ) 來判斷)

 (3)如果兩個都是字串,每個位置的字元都一樣,那麼相等,否則不相等。

 (4)如果兩個值都是true,或是false,那麼相等

 (5)如果兩個值都引用同一個物件或是函式,那麼相等,否則不相等

 (6)如果兩個值都是null,或是undefined,那麼相等

解決方案:Bignumber.js

github:https://github.com/MikeMcl/bignumber.js/

api:https://mikemcl.github.io/bignumber.js/

1. npm i bignumber.js

2. import BigNumber from 'bignumber.js'

3. 字串比較是否相等
   const a = new BigNumber('21423916781467932410578214')
   const b = new BigNumber('21423916781467932410578214')
   a.toString()
   b.toString()

   console.log(a.isEqualTo(b)) // true

更多用法可參考:

加法 plus

  • 語法
    .plus(n [, base])
    • 引數值
      • n(必需):number|string|BigNumber參與計算的數字
      • base:number進位制 (預設為十進位制)
    • 返回值
      BigNumber
  • 舉例
0.1 + 0.2 // 0.30000000000000004

x = new BigNumber(0.1)

y = x.plus(0.2) // '0.3'

BigNumber(0.7).plus(x).plus(y) // '1'

x.plus('0.1', 8) // '0.225'

減法 minus

  • 語法
    .minus(n [, base])
    • 引數值
      • n(必需):number|string|BigNumber參與計算的數字
      • base:number進位制 (預設為十進位制)
    • 返回值
      • BigNumber
  • 舉例
  • 0.3 - 0.1 // 0.19999999999999998
    
    x = new BigNumber(0.3)
    
    x.minus(0.1) // '0.2'
    
    x.minus(0.6, 20) // '0'

乘法 multipliedBy

  • 語法
    .times(n [, base])
    • 引數值
      • n(必需):number|string|BigNumber參與計算的數字
      • base:number進位制 (預設為十進位制)
    • 返回值
      • BigNumber
  • 舉例
0.6 * 3 // 1.7999999999999998

x = new BigNumber(0.6)

y = x.multipliedBy(3) // '1.8'

BigNumber('7e+500').times(y) // '1.26e+501'

x.multipliedBy('-a', 16) // '-6'

除法 dividedBy

  • 語法
    .div(n [, base])
    • 引數值
      • n(必需):number|string|BigNumber參與計算的數字
      • base:number進位制 (預設為十進位制)
    • 返回值
      • BigNumber
  • 舉例
x = new BigNumber(355)

y = new BigNumber(113)

x.dividedBy(y) // '3.14159292035398230088'

x.div(5) // '71'

x.div(47, 16) // '5'

除法-取整 dividedToIntegerBy

  • 語法
    .idiv(n [, base])
    • 引數值
      • n(必需):number|string|BigNumber參與計算的數字
      • base:number進位制 (預設為十進位制)
    • 返回值
      • BigNumber
  • 舉例
x = new BigNumber(5)

y = new BigNumber(3)

x.dividedToIntegerBy(y) // '1'

x.idiv(0.7) // '7'

x.idiv('0.f', 16) // '5'

除法-取餘 modulo

  • 語法
    .mod(n [, base])
    • 引數值
      • n(必需):number|string|BigNumber參與計算的數字
      • base:number進位制 (預設為十進位制)
    • 返回值
      • BigNumber
  • 舉例
1 % 0.9 // 0.09999999999999998

x = new BigNumber(1)

x.modulo(0.9) // '0.1'

y = new BigNumber(33)

y.mod('a', 33) // '3'

指數運算 exponentiatedBy

  • 語法
    .pow(n [, m])
    • 引數值
      • n(必需):number|string|BigNumber參與計算的數字
      • m:number|string|BigNumber指數
    • 返回值
      • BigNumber
  • 舉例
Math.pow(0.7, 2) // 0.48999999999999994

x = new BigNumber(0.7)

x.exponentiatedBy(2) // '0.49'

BigNumber(3).pow(-2) // '0.11111111111111111111'

開平方 squareRoot

  • 語法
    .sqrt()
  • 舉例
x = new BigNumber(16)

x.squareRoot() // '4'

y = new BigNumber(3)

y.sqrt() // '1.73205080756887729353'

四捨五入 toFixed

  • 語法
    .toFixed([dp [, rm]])
    • dp(必需):number保留小數位數
    • rm:number
  • 舉例
x = 3.456

y = new BigNumber(x)

x.toFixed() // '3'

y.toFixed() // '3.456'

y.toFixed(0) // '3'

x.toFixed(2) // '3.46'

y.toFixed(2) // '3.46'

y.toFixed(2, 1) // '3.45' (ROUND_DOWN)

x.toFixed(5) // '3.45600'

y.toFixed(5) // '3.45600'