gracekrcx / weekly-notes

4 stars 0 forks source link

js 浮點數運算 #109

Open gracekrcx opened 3 years ago

gracekrcx commented 3 years ago

js 在計算浮點數時

 // 0.1 和0.2 都轉化成二進制後再進行運算
0.00011001100110011001100110011001100110011001100110011010 +
0.0011001100110011001100110011001100110011001100110011010 =
0.0100110011001100110011001100110011001100110011001100111

// 轉成十進制正好是0.30000000000000004

文章裡提供了一個加法的解決方式 通常的解法就是換到整數去做運算,然後再轉回有小數點

/** 
*精確加法
*/ 
function  add ( num1 ,  num2 )  { 
  const  num1Digits  =  ( num1 . toString ( ) . split ( '.' ) [ 1 ]  ||  '' ) . length ; 
  const  num2Digits  =  ( num2 . toString ( ) . split ( '.' ) [ 1 ]  ||  '' ). length ; 
  const  baseNum  =  Math . pow ( 10 ,  Math . max ( num1Digits ,  num2Digits ) ) ; 
  return  ( num1  *  baseNum  +  num2  *  baseNum )  /  baseNum ; 
}

備註:如果有預期,例如:資料來源是 1.2345 + 2.3 最後呈現固定兩位小數 (1) 加法時還是用上方的公式 (2) 那在兩位小數之後的位數,如何處理就必須討論確認

比較驚訝的是底下

35.41 * 100 = 3540.9999999999995
0.14 / 100  =  0.0014000000000000002

但如果套在上方加法運算

add(35.41, 0.1)

// 3550.9999999999995 / 100
// 又變回  35.51 

toFixed 的誤差

1.005.toFixed(2) // 1.00

// toFixed 會四捨五入,但這個例子沒有 

如果單純是數據展示,可用底下解法

parseFloat(1.1000000000000001.toPrecision(12)) === 1.1  // True

參考文章

JavaScript浮點數陷阱及解法 [開發經驗分享][JavaScript]浮點數運算出現一堆小數位數 js中小数四舍五入和浮点数的研究 javascript浮點數的陷阱