【JS】About precision loss, causes and solutions

Precision loss case

Loss of precision is a common problem in front-end development, especially when it comes to floating point calculations.

Here are some common cases of precision loss:

1 Simple addition and subtraction

0.1 + 0.2 // 结果为 0.30000000000000004
0.3 - 0.1 // 结果为 0.19999999999999996

// 这是因为浮点数的二进制表示无法准确表示某些十进制小数,导致计算结果存在微小的误差。

2 Multiplication and division

0.1 * 0.2 // 结果为 0.020000000000000004
0.3 / 0.1 // 结果为 2.9999999999999996

// 在进行乘法和除法时,浮点数计算结果的精度问题更为突出,可能会产生更大的误差。

3 Comparison operations

0.1 + 0.2 === 0.3 // 结果为 false

// 直接比较浮点数可能会导致不准确的结果,因为计算结果的微小误差可能使它们不完全相等。

Reasons for loss of accuracy

The main reason is that the computer internally uses binary floating point number representation, not decimal. This binary representation cannot accurately represent certain decimal fractions in some cases, resulting in a loss of precision.

Here are a few common reasons for loss of accuracy:

  1. Unexactly representable decimal fractions : Some decimal fractions cannot be accurately represented as finite-length binary decimals. For example, decimal fractions such as 0.1 and 0.2 are infinitely recurring decimals in binary representation, so when represented internally by a computer with a limited number of digits, there will be rounding errors, resulting in a loss of precision.
  2. Rounding error : Since the number of digits in floating point numbers is limited, for decimal fractions that cannot be represented accurately, the computer rounds to approximate their value. This rounding operation introduces errors and causes differences between calculated results and expected values.
  3. Cumulative errors in arithmetic operations : When performing a series of floating-point arithmetic operations, rounding errors can accumulate and cause a loss of precision. Each operation introduces some errors, which gradually accumulate over multiple operations, resulting in reduced accuracy of the final result.
  4. Inaccuracy of comparison operations : Due to the limited representation precision of floating-point numbers, direct comparison of floating-point numbers may lead to inaccurate results. Small rounding errors can cause two floating-point numbers that appear to be equal to be considered unequal when compared.
  5. Limitation of numerical range : The representation range of floating point numbers is limited. Values ​​outside the range may cause overflow or underflow, thus affecting the accuracy of calculation results.

How to solve the problem of precision loss

Here are some common workarounds:

  1. Use integers for calculations : Convert floating point numbers to integers for calculations whenever possible. For example, convert a floating point number to an integer by multiplying the number of decimal places by a fixed multiple, perform the calculation, and then convert the result back to a floating point number. This can reduce precision issues in floating point calculations.
  2. Use specialized libraries or tools : In handling scenarios that require high-precision calculations, some specialized libraries or tools can be used. For example, libraries such as Decimal.js, Big.js or BigNumber.js in JavaScript provide high-precision mathematical calculation functions to avoid the problem of precision loss.
  3. Avoid direct comparisons of floating-point numbers : Due to precision issues, direct comparisons of floating-point numbers may lead to inaccurate results. In situations where you need to compare floating point numbers, you can use error bounds for comparison instead of using exact equality judgments.
  4. Limit the number of decimal places : For some specific application scenarios, you can limit the number of decimal places for floating point numbers to reduce the impact of precision loss. For example, currency calculations are often limited to two decimal places.
  5. Use an appropriate rounding strategy : When rounding is required, choose an appropriate rounding strategy to meet actual needs. Common rounding strategies include rounding, rounding up, rounding down, etc.
  6. Pay attention to the range of values : When performing floating point calculations, pay attention to the range of values. Values ​​outside the representation range of floating point numbers may cause loss of precision or overflow problems.

In summary, dealing with loss of precision on the front end requires careful handling of calculations and comparisons of floating point numbers, and consideration of using integer arithmetic, specialized libraries or tools, and appropriate rounding strategies to solve the problem. Depending on the specific application scenario, choosing an appropriate method can effectively reduce the impact of accuracy loss.

In some simple scenarios, some techniques can be used to solve the problem of loss of precision in floating-point calculations.

For example:

// 使用这些方法,仍然需要注意数值范围、舍入策略和比较运算等方面的问题,根据具体的应用场景进行适当的调整和处理。

// 加法运算
function add(a, b) {
    
    
  const precision = Math.max(getPrecision(a), getPrecision(b));
  const multiplier = Math.pow(10, precision);
  return (Math.round(a * multiplier) + Math.round(b * multiplier)) / multiplier;
}

// 减法运算
function subtract(a, b) {
    
    
  return add(a, -b);
}

// 乘法运算
function multiply(a, b) {
    
    
  const precision = getPrecision(a) + getPrecision(b);
  const multiplier = Math.pow(10, precision);
  return (Math.round(a * multiplier) * Math.round(b * multiplier)) / (multiplier * multiplier);
}

// 除法运算
function divide(a, b) {
    
    
  const precision = getPrecision(a) - getPrecision(b);
  const divisor = Math.pow(10, precision);
  return (Math.round(a / b * divisor)) / divisor;
}

// 获取浮点数的小数位数
function getPrecision(num) {
    
    
  const str = String(num);
  const decimalIndex = str.indexOf('.');
  return decimalIndex === -1 ? 0 : str.length - decimalIndex - 1;
}

The above code defines four basic arithmetic operations: add(addition), subtract(subtraction), multiply(multiplication) and divide(division). These methods perform calculations by converting floating point numbers to integers and rounding when necessary to reduce the impact of loss of precision.

Note that these methods only provide a simple way to deal with loss of precision and do not address all possible cases . In some specific scenarios, you may need to use specialized high-precision mathematics libraries, such as Decimal.js, Big.js or BigNumber.js, etc., to obtain more accurate calculation results.

Guess you like

Origin blog.csdn.net/qq_53931766/article/details/132455164
Recommended