切換語言為:簡體

JavaScript中的浮點數計算

  • 爱糖宝
  • 2024-09-04
  • 2045
  • 0
  • 0

前言

在使用JavaScript計算浮點數時,會出現精度丟失的問題,其實不止是JavaScript,只要是遵循IEEE 754標準的語言都存在這個問題

為什麼會精度丟失?

  1. 表示範圍
    浮點數使用二進制表示,某些十進制數無法精確表示。例如,0.1 和 0.2 在二進制中是無限迴圈小數,因此只能近似表示。

  2. 精度限制
    浮點數在計算機中是以固定的位數儲存的。對於雙精度浮點數(如 JavaScript 中的 Number 型別),它通常使用64位,其中包括符號位1位、指數位11位和尾數位53位。這種限制導致了某些運算的結果無法精確表示。

  3. 累積誤差
    在進行多次浮點運算時,微小的誤差會逐漸累積,導致最終結果遠離預期值。

0.1 + 0.2 === 0.3?

答案是錯誤的

const a = 0.1;
const b = 0.2;
console.log(a + b); // 0.30000000000000004

JavaScript中的浮點數計算

這就是由於精度丟失的問題

其中0.1轉換為二進制的過程為

將 0.1 轉換為二進制的過程如下:

  • 0.1 × 2 = 0.2 → 整數部分為 0

  • 0.2 × 2 = 0.4 → 整數部分為 0

  • 0.4 × 2 = 0.8 → 整數部分為 0

  • 0.8 × 2 = 1.6 → 整數部分為 1

  • 0.6 × 2 = 1.2 → 整數部分為 1

  • 0.2 × 2 = 0.4 → 整數部分為 0

  • ...

如此迴圈下去,0.1 在二進制中表現為 0.00011001100110011...,這是一個無限迴圈的小數。

0.2同理,所以他們相加得到的二進制數也是個無限迴圈的小數,這也就是造成進度丟失的根本原因

解決方式

  • 將其變為整數再相加

function add(num1, num2) {
    // 將輸入的數字轉換為字串,找到小數位數
    const str1 = num1.toString();
    const str2 = num2.toString();
    
    const decimalPlaces1 = str1.includes('.') ? str1.split('.')[1].length : 0;
    const decimalPlaces2 = str2.includes('.') ? str2.split('.')[1].length : 0;
    
    // 計算最大的位數
    const maxDecimalPlaces = Math.max(decimalPlaces1, decimalPlaces2);
    
    // 將數字轉換為整數
    const factor = Math.pow(10, maxDecimalPlaces);
    const intNum1 = Math.round(num1 * factor);
    const intNum2 = Math.round(num2 * factor);
    
    // 進行加法運算
    const sum = intNum1 + intNum2;
    
    // 將結果轉換回浮點數
    return sum / factor;
}

// 示例使用
console.log(add(0.1, 0.2)); // 輸出: 0.3
console.log(add(0.1, 0.3)); // 輸出: 0.4
console.log(add(1.5, 2.3)); // 輸出: 3.8

function add(num1, num2) {

  • 函式定義:定義一個名為 add 的函式,接受兩個引數 num1 和 num2,它們都是需要相加的數字。

const str1 = num1.toString(); 
const str2 = num2.toString();

  • 轉換為字串:將 num1 和 num2 轉換為字串格式,以便後續處理小數位數。

const decimalPlaces1 = str1.includes('.') ? str1.split('.')[1].length : 0;
const decimalPlaces2 = str2.includes('.') ? str2.split('.')[1].length : 0;

  • 計算小數位數

    • 使用 includes 方法檢查字串中是否包含小數點 .

    • 如果包含小數點,使用 split 方法將字串分割成兩部分,並獲取小數部分的長度。

    • 如果不包含小數點,則小數位數為 0。

const maxDecimalPlaces = Math.max(decimalPlaces1, decimalPlaces2);

  • 確定最大小數位數:使用 Math.max 函式找到兩個數字中小數位數的最大值,以便統一處理。

const factor = Math.pow(10, maxDecimalPlaces);

  • 計算因子:計算 10 的最大小數位數的冪,目的是將浮點數轉換為整數。例如,如果最大小數位數是 2,則因子為 100。

const intNum1 = Math.round(num1 * factor); 
const intNum2 = Math.round(num2 * factor);

  • 轉換為整數

    • 將 num1 和 num2 乘以因子,得到相應的整數。

    • 使用 Math.round 方法確保在轉換過程中不會產生四捨五入的誤差。

const sum = intNum1 + intNum2;

  • 進行加法運算:將兩個整數相加,得到 sum

bash程式碼解讀複製程式碼return sum / factor;

  • 返回結果:將總和除以因子,轉換回浮點數,並返回結果。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.