【问题标题】:Javascript wrongfully changes the result of a simple multiplication. How can I fix it?Javascript 错误地改变了简单乘法的结果。我该如何解决?
【发布时间】:2017-06-02 12:39:09
【问题描述】:

function roundUp(num, precision) {
  return Math.ceil(num * precision) / precision;
}

var num = 0.07;
var precision = 100;
console.log(roundUp(num, precision));

当函数的参数是 0.07 和 100 时,“num * precision”乘法得到类似“7.000000000001”的结果,ceil 函数将其四舍五入为 8。我无缘无故得到了完全不同的结果。

我该如何解决这个问题?我有 big.js 但无法解决。

【问题讨论】:

  • 会有什么结果?
  • 您已将此标记为 bigdecimal,但您没有使用任何可以解决您的问题的 bigdecimal 库或数据类型。上面的每个人都在向您指出浮点精度,对于标准浮点类型(四舍五入到基数 2,而不是基数 10),您总是会遇到这种情况

标签: javascript math floating-point bigdecimal


【解决方案1】:

这里的另一个天真的尝试是功能是天花板。这试图使错误因子将数字降低 EPSILON 倍,以便我们得到 6.9999999.. 而不是 7.00000000..1

又是一次天真的尝试!

function roundUp(num, precision) {
      return Math.ceil((num * precision) - (num * precision * Number.EPSILON)) / precision;
}

console.log(roundUp(0.07, 100))
console.log(roundUp(0.03, 100))
console.log(roundUp(0.002, 1000))
console.log(roundUp(0.00222, 1000))
console.log(roundUp(0.006, 1000))
console.log(roundUp(0.00600000000000000000001, 10000000000000000000));//broken
console.log(roundUp(0.006001, 10000000));
console.log(roundUp(0.0333, 1000))
console.log(roundUp(0.07777777, 10))
console.log(roundUp(0.07777777, 100))
console.log(roundUp(0.07777777, 1000))
console.log(roundUp(0.07777777, 10000))
console.log(roundUp(0.07777777, 100000))
console.log(roundUp(0.07777777, 1000000))

console.log(roundUp(0.33333333333333, 1000000))

【讨论】:

  • 这可能会在 OP 的情况下提供“正确”的值,但由于浮动数学缺陷,在其他一些情况下肯定会以“不正确”的值结束。此外,将每个数字转换为字符串然后再转换回数字将非常低效。
  • 你对 toFixed 的使用是愚蠢的;您将数字转换为以 10 为底的字符串,然后立即将其转换回以 2 为底的浮点数。充其量你运气好,让它在回弹时以相反的方式旋转,但这真的只是偶然。
  • @AndrewSklyarevsky ,Dave 我同意你的两个观点。我通常会看到 EPSILON 因子可能是 10-12 位十进制数字,因此放弃该部分是一种天真的尝试。我确定这并不像你们所说的那样准确。
猜你喜欢
  • 1970-01-01
  • 2014-12-05
  • 2019-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-24
相关资源
最近更新 更多