JS浮點計算問題

來源:互聯網
上載者:User

標籤:

問題

用js進行浮點數計算,結果可能會“超出預期”,大部分計算結果還是對的,但是我們可不想在計算這麼嚴謹的事情上還有意外的驚喜。比如:

  • 0.3 + 0.6 = 0.8999999999999999
  • 0.3 - 0.2 = 0.09999999999999998
  • 0.3 * 1.5 = 0.44999999999999996
  • 0.3 / 0.1 = 2.9999999999999996

看完這幾個計算結果,如果你沒用過js,你可能會有點崩潰。我只能說,這就是js的魅力所在。

分析

在這之前,你需要知道以下幾點:

  • js中數字類型只有Number;
  • js的Number是IEEE 754標準的64-bits的雙精確度數值

網上有很多關於此問題的解釋,由於電腦是用二進位來儲存和處理數字,不能精確表示浮點數,而js中沒有相應的封裝類來處理浮點數運算,直接計算會導致運算精度丟失。其實進階語言(c#,java)也存在此問題,只不過它們自己內部做了處理,把這種精度差異給屏蔽掉了。有些小數轉換為二進位位元是無窮的(有迴圈),但是64位中小數最多隻有52位,因此對於位元超過的相當於被截取了,導致了精度的丟失。這個地址可以用來浮點數和IEEE 754標準的64-bits的互轉(背後是二進位的轉換),用這個我們來驗證下0.3-0.2。

  • 0.3轉換後為0.299999999999999988897769753748
  • 0.2轉換後為0.200000000000000011102230246252
  • 0.299999999999999988897769753748-0.200000000000000011102230246252=0.099999999999999977795539507496

這和js直接計算的結果0.09999999999999998想吻合。

分析下來,終於明白並不是js自身發育不良,只是沒有及時補充營養,我們只能另想出路了。

解決方案

網上已經存在很多解決方案了,我這裡也沒有特別的方法,但是網上有很多方法只搞定了一半,仍然存在bug。大部分解決方案的思路是將浮點數計算轉換為整數計算,整數計算當然是沒有bug的啦。前面說網上部分方法只搞對了一半,對的一半是乘除法,加減法仍然有問題,因為加減法還存在浮點數的直接運算。

附:沒有bug的代碼。

function add(a, b) {    var c, d, e;    try {        c = a.toString().split(".")[1].length;    } catch (f) {        c = 0;    }    try {        d = b.toString().split(".")[1].length;    } catch (f) {        d = 0;    }    return e = Math.pow(10, Math.max(c, d)), (mul(a, e) + mul(b, e)) / e;}function sub(a, b) {    var c, d, e;    try {        c = a.toString().split(".")[1].length;    } catch (f) {        c = 0;    }    try {        d = b.toString().split(".")[1].length;    } catch (f) {        d = 0;    }    return e = Math.pow(10, Math.max(c, d)), (mul(a, e) - mul(b, e)) / e;}function mul(a, b) {    var c = 0,        d = a.toString(),        e = b.toString();    try {        c += d.split(".")[1].length;    } catch (f) {}    try {        c += e.split(".")[1].length;    } catch (f) {}    return Number(d.replace(".", "")) * Number(e.replace(".", "")) / Math.pow(10, c);}function div(a, b) {    var c, d, e = 0,        f = 0;    try {        e = a.toString().split(".")[1].length;    } catch (g) {}    try {        f = b.toString().split(".")[1].length;    } catch (g) {}    return c = Number(a.toString().replace(".", "")), d = Number(b.toString().replace(".", "")), mul(c / d, Math.pow(10, f - e));}

 

JS浮點計算問題

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.