首页 > 解决方案 > TypeScript:我无法让浮点/十进制数学正常工作。(82.80000000000001,但应该是 82.8)

问题描述

问题:

我在 JavaScript/Typescript 中遇到小数/浮点数学问题。我知道有关这些问题的帖子,但我没有运气。

期望的结果:

82.8

结果:

82.80000000000001

什么工作:

total += (array[i] * weight[i] * 100) / 100;行正常工作,但相同的逻辑不适用于total.

我试过的:

  1. 在另一个函数中,我将值乘以 10 或 100。这可行,但我无法让它在我的情况下工作。
const remainder: number = ((1 - Math.sqrt(value)) * 10) / 10;
  1. 人们建议使用toFixed(2);,但这会将数字的类型转换为字符串,这是我不想要的。

计算加权平均.tsx:

// Calculate Weighted Average
export const calculateAverageWeighted = (array: Array<number>, weight: Array<number>) => {
  // Check If Data Exists
  if (array.length >= 1) {
    // Weight Length: Must Equal Array Length
    if (weight.length == array.length) {
      // Weight Sum: Must Equal 1 Or 100
      if (weight.reduce((total: number, value: number) => { return total + value }) === 1 || weight.reduce((total: number, value: number) => { return total + value }) === 100) {
        // Total
        let total: number = 0;

        // Iterate Over Array
        let i: number = 0;
        while (i < array.length) {
          // Add To Total
          total += (array[i] * weight[i] * 100) / 100;

          // Increase I
          i++;
        }

        // IMPORTANT: FLOAT MATH (NOT WORKING HERE)
        return (total * 100) / 100;
      }
      else {
        // Error
        throw new Error('Error: Values of Weight Array must be equal to 1 or 100 (calculateAverageWeighted)');
      }
    }
    // Array Length Is Less Than Weight Length
    else if (array.length < weight.length || array.length > weight.length) {
      // Error
      throw new Error('Error: Length of weight must be equal to input Array (calculateAverageWeighted)');
    }
  }
  else {
    // Error
    throw new Error('Error: Empty Array (calculateAverageWeighted)');
  }
};

标签: javascripttypescriptfloating-pointdecimal

解决方案


典型的浮点值是二元有理数,一些 n 位整数乘以 2 的幂,其中n指数范围是有限的。

类似代码total += (array[i] * weight[i] * 100) / 100;执行 2 乘法、除法和加法。每个乘积、商和总和可能与数学预期的结果不完全相同,因为结果被四舍五入并保存到最接近的二元有理数。

82.8 本身并不是完全可编码的。相反,最接近的值是

82.7999999999999971578290569595992565155029296875
82.8                                             // OP's hoped for result (not possible)
82.80000000000001136868377216160297393798828125  // Next best choice.
82.80000000000001                                // OP's reported result

相反,接受结果与数学结果不完全相同,并将报告的结果限制为四舍五入的结果,可能是 14-15 位有效数字。

// 345678901234    
82.800000000000                                  // 14 significant places

或者使用整数执行数学运算:将所有内容缩放 0.001。

或者使用十进制浮点数。(仍然 1.0/7.0 也不准确)

或使用基于精确的数学库执行。

或者接受 82.80000000000001足够简单。


推荐阅读