日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

ieee754浮点数转换工具_关于JS浮点数运算不精确的原因和解决方案

發布時間:2024/7/23 javascript 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ieee754浮点数转换工具_关于JS浮点数运算不精确的原因和解决方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景

之前在一個項目中,涉及到了金額,協議組定的標準是按照分的單位進行傳遞的,但是交互上,web頁面中為了更友好的體驗,是使用的元作為單位的,這個時候就需要轉換一下單位

本來是很簡單的一個轉化的需求,在和后端聯調的時候發現,保存的時候返回了參數錯誤,原因就是由于js浮點數精度帶來的影響,導致保存的時候保存的位數特別多。

之前的開發過程中,對這個不精確的問題只是了解,有問題了就parseInt一下,但沒有去細想過要怎么解決,所以今天整理了一下之后分享一下,先了解下原因,再看下怎么解決和規避

問題

輸入金額 0.55,我傳遞之后應該乘 100 后下發,正常來說應該傳的是55,但是實際上,由于精度丟失,最后的結果如下圖所示:

那追根溯源,到底為什么會產生精度丟失的問題呢?

計算機底層只有0 和 1, 所以所有的運算最后實際上都是二進制運算。十進制整數利用輾轉相除的方法可以準確地轉換為二進制數,但浮點數呢?

先看下面一張圖,是關于IEEE 754標準(IEEE二進位浮點數算術標準(IEEE Standard for Floating-Point Arithmetic)的標準編號):

這個標準是JS的浮點數的實現標準,大概解釋一下這張圖就是:

  • 第一位是符號位
  • 中間11位代表的是指數位
  • 最后的52位代表尾數位

也就是說,浮點數最終在運算的時候實際上是一個符合該標準的二進制數

我們可以看一個例子:

為了驗證該例子,我們得先知道怎么將浮點數轉換為二進制,整數我們可以用除2取余的方式,小數我們則可以用乘2取整的方式。

0.1轉換為二進制:

  • 0.1 * 2,值為0.2,小數部分0.2,整數部分0
  • 0.2 * 2,值為0.4,小數部分0.4,整數部分0
  • 0.4 * 2,值為0.8,小數部分0.8,整數部分0
  • 0.8 * 2,值為1.6,小數部分0.6,整數部分1
  • 0.6 * 2,值為1.2,小數部分0.2,整數部分1
  • 0.2 * 2,值為0.4,小數部分0.4,整數部分0
  • 從0.2開始循環

0.2轉換為二進制:

  • 可以直接參考上述,肯定最后也是一個循環的情況

所以最終我們能得到兩個循環的二進制數:

0.1:0.0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1100 ...

0.2:0.0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 ...

這兩個的和的二進制就是:

sum:0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 ...

所以最終我們只能得到和的近似值(按照IEEE 754標準保留 52位,按 0舍1入 來取值)

利用按權相加法,sum的十進制數則為:

sum ≈ 0.30000000000000004

這個例子說明了什么?

說明JS浮點數精度的缺失實際上是因為浮點數的小數部分無法用二進制很精準的轉換出來,而以近似值來進行運算的話,肯定就存在精度的問題

解決

了解了真相之后,我們可以怎么處理呢?

我的項目中是直接parseInt了一下,因為誤差很小,可以忽略不計。

但后來想想不能這么就放過去了,這種一刀切的方法太暴力了,萬一涉及到需要特別精確的場景,這種方法會有問題。

所以,最好的辦法還是需要找方法提高精度,直接規避。

思路其實非常簡單,既然浮點數的情況下會丟失精度,那我們所有運算的時候都先小浮點數轉換為整數,等計算完之后,再按比例轉換會浮點數,這樣就避免了再二進制十進制轉換的時候計算機的精度問題。

比如上面的加法的例子,我們定義一個工具函數add:

const

現在我們再來看看結果:

但有個問題,我們之前還有個例子,0.55在乘的時候就會產生精度問題,所以這里我們再優化一下,把一個數變成整數,是不是也可以理解為將其變成字符串后把小數點去掉再轉回數字,這樣效果和相乘的效果不是一樣的嗎:

const

這樣就解決了。

當然,這只是考慮了最簡單的情況,比如如果位數不同還要特殊處理下。不過只要思路有了,后續的就屬于添磚加瓦了,考慮得很全面的話,可以考慮封裝成一個庫,這篇文章就權當拋磚引玉吧。

總結

以上是生活随笔為你收集整理的ieee754浮点数转换工具_关于JS浮点数运算不精确的原因和解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。