浮點數精確度誤差問題

2019/10/26 Program

前言

在任何程式語言你可能會發現浮點數相加精確度的問題,試著 0.1 + 0.2 看看會發生什麼事情?多數程式語言會跑出 0.30000000000000004 的結果。因為電腦是二進制而我們人看的是十進制,此外會遇到循環數除不盡問題,因此會產生浮點數不精確的結果。詳細內容可以參考這個網站

解決辦法

在任何語言中幾乎都有支援大數的函式庫,decimal 為處理數字精準度的模組。

  • Python3
from decimal import *

a = Decimal('.1')
b = Decimal('.2')
print(a+b)
from decimal import *

# 浮點數相減
def substract(a,b):
    bigA=Decimal(str(a))
    bigB=Decimal(str(b))
    return bigA-bigB
# 浮點數相加
def addstract(a,b):
    bigA=Decimal(str(a))
    bigB=Decimal(str(b))
    return bigA+bigB
# 浮點數相除
TWOPLACES = Decimal(10) ** -2  
def div(x, y, fp=TWOPLACES):
    return (x / y).quantize(fp)
# 浮點數相乘
def mul(x, y, fp=TWOPLACES):
    return (x * y).quantize(fp)

參考

  • Java
//加    
function floatAdd(arg1, arg2) {
  var r1, r2, m;
  try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
  try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
  m = Math.pow(10, Math.max(r1, r2));
  return (arg1 * m + arg2 * m) / m;
}

//减    
function floatSub(arg1, arg2) {
  var r1, r2, m, n;
  try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
  try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
  m = Math.pow(10, Math.max(r1, r2));
  //動態控制精度長度   
  n = (r1 >= r2) ? r1 : r2;
  return ((arg1 * m - arg2 * m) / m).toFixed(n);
}
  • JavaScript
//加    
floatAdd = (arg1, arg2) => {
  var r1, r2, m;
  try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
  try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
  m = Math.pow(10, Math.max(r1, r2));
  return (arg1 * m + arg2 * m) / m;
}

//减    
floatSub = (arg1, arg2) => {
  var r1, r2, m, n;
  try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
  try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
  m = Math.pow(10, Math.max(r1, r2));
  //動態控制精度長度     
  n = (r1 >= r2) ? r1 : r2;
  return ((arg1 * m - arg2 * m) / m).toFixed(n);
}

Search

    Table of Contents