JavaScript 数学,四舍五入到小数点后两位

IT技术 javascript math
2021-02-01 05:04:52

我有以下 JavaScript 语法:

var discount = Math.round(100 - (price / listprice) * 100);

这四舍五入到整数。如何返回带有两位小数的结果?

6个回答

注意 - 如果 3 位精度很重要,请参阅编辑 4

var discount = (price / listprice).toFixed(2);

toFixed 将根据超过 2 位小数的值为您四舍五入。

示例:http : //jsfiddle.net/calder12/tv9HY/

文档:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed

编辑- 正如其他人所提到的,这会将结果转换为字符串。为避免这种情况:

var discount = +((price / listprice).toFixed(2));

编辑 2 - 正如评论中所提到的,该函数在某些精度上失败,例如在 1.005 的情况下,它将返回 1.00 而不是 1.01。如果这种程度的准确性很重要,我找到了这个答案:https : //stackoverflow.com/a/32605063/1726511这似乎适用于我尝试过的所有测试。

但是,需要进行一个小的修改,上面链接的答案中的函数在舍入为 1 时返回整数,因此例如 99.004 将返回 99 而不是 99.00,这不适合显示价格。

编辑 3 - 似乎在实际返回时使用 toFixed 仍然搞砸了一些数字,这个最终编辑似乎有效。天啊这么多返工!

var discount = roundTo((price / listprice), 2);

function roundTo(n, digits) {
  if (digits === undefined) {
    digits = 0;
  }

  var multiplicator = Math.pow(10, digits);
  n = parseFloat((n * multiplicator).toFixed(11));
  var test =(Math.round(n) / multiplicator);
  return +(test.toFixed(digits));
}

请参阅此处的小提琴示例:https : //jsfiddle.net/calder12/3Lbhfy5s/

编辑 4 - 你们杀了我。Edit 3 在负数上失败,没有深入研究为什么在进行舍入之前将负数变为正数,然后在返回结果之前将其转回更容易处理。

function roundTo(n, digits) {
    var negative = false;
    if (digits === undefined) {
        digits = 0;
    }
    if (n < 0) {
        negative = true;
        n = n * -1;
    }
    var multiplicator = Math.pow(10, digits);
    n = parseFloat((n * multiplicator).toFixed(11));
    n = (Math.round(n) / multiplicator).toFixed(digits);
    if (negative) {
        n = (n * -1).toFixed(digits);
    }
    return n;
}

小提琴:https : //jsfiddle.net/3Lbhfy5s/79/

确保您使用 toFixed 的项目是一个数字,您可以先 parseFloat 它。
2021-03-20 05:04:52
将数字转换为字符串,再返回数字,这似乎是一项艰巨的工作。我发现这Math.round(x * 100) / 100;是四舍五入到两位小数的最简单、最简单的方法。
2021-03-21 05:04:52
说真的,这样做的目的是回答最初的问题,这个答案就是这样做的。如果您一定有更好的答案,请添加它,但挑剔一个 6 年前的答案如何舍入到小数点后 2 位,因为它没有舍入到小数点后 20 位,这正是本网站的问题所在。
2021-03-25 05:04:52
否决,因为它非常低效(在我的机器上它比 Math.round 花费的时间长 400jsperf.com/round-numbers-to-2-digits
2021-03-29 05:04:52
.toFixed 返回一个字符串而不是数字 - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-04-06 05:04:52

如果您使用一元加号将字符串转换为 MDN 上记录的数字

例如:+discount.toFixed(2)

@neaumusic 你可以使用 Date.now()
2021-03-23 05:04:52
离合器,我现在也将它与 +new Date() 一起使用
2021-03-25 05:04:52
使用加号将字符串转换为数字的好方法
2021-03-27 05:04:52
你的答案不起作用:parseFloat((1.005).toFixed(2))应该给1.01,不1.00
2021-04-04 05:04:52
真的,你应该使用parseFloat( discount.toFixed(2) )而不是强制类型强制,因为它对其他人(以及你以后)更明显
2021-04-10 05:04:52

函数 Math.round() 和 .toFixed() 旨在四舍五入到最接近的整数。在处理小数和使用 Math.round() 的“乘除”方法或 .toFixed() 的参数时,您会得到不正确的结果。例如,如果您尝试使用 Math.round(1.005 * 100) / 100 对 1.005 进行四舍五入,那么您将获得 1 的结果,使用 .toFixed(2) 获得 1.00 的结果,而不是获得 1.01 的正确答案。

您可以使用以下方法解决此问题:

Number(Math.round(100 - (price / listprice) * 100 + 'e2') + 'e-2');

添加 .toFixed(2) 以获得您想要的两位小数。

Number(Math.round(100 - (price / listprice) * 100 + 'e2') + 'e-2').toFixed(2);

您可以创建一个函数来为您处理舍入:

function round(value, decimals) {
    return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
}

示例:https : //jsfiddle.net/k5tpq3pd/36/

另类

您可以使用原型向 Number 添加圆形函数。我不建议在这里添加 .toFixed() 因为它会返回一个字符串而不是数字。

Number.prototype.round = function(decimals) {
    return Number((Math.round(this + "e" + decimals)  + "e-" + decimals));
}

并像这样使用它:

var numberToRound = 100 - (price / listprice) * 100;
numberToRound.round(2);
numberToRound.round(2).toFixed(2); //Converts it to string with two decimals

示例 https://jsfiddle.net/k5tpq3pd/35/

资料来源:http : //www.jacklmoore.com/notes/rounding-in-javascript/

+1 反馈!我已经根据您的反馈重新定义了答案,所以希望更多人会发现它更有帮助和正确性
2021-03-13 05:04:52
他们可能已经投了反对票,因为这并不是一个真正的错误。 Math.round()意味着四舍五入到最接近的整数,人们通常不赞成并尽量不改变这样的内置方法,以防有人期望该功能就像他们在你背后编写代码时那样。但是您的代码是合理的,并且 +1 指出了Math.round().
2021-03-26 05:04:52
这不适用于某些负值。例如,Number(Math.round(-1.225 + 'e2') + 'e-2')回报-1.22Number(Math.round(1.225 + 'e2') + 'e-2')回报1.23
2021-03-30 05:04:52
这种方法不适用于字符串表示已经有指数的数字。1e+21例如,任何或更高的返回值NaN
2021-04-01 05:04:52
你如何强制2位小数?在您的示例中,具有 1 个小数的数字不会用“0”填充第二个小数位,例如“1.3”四舍五入为“1.3”而不是“1.30”。
2021-04-07 05:04:52

要获得两位小数的结果,您可以这样做:

var discount = Math.round((100 - (price / listprice) * 100) * 100) / 100;

要舍入的值乘以 100 保留前两位数字,然后除以 100 得到实际结果。

@DejayClayton 实际上,这是正确的方法,无需经历转换为字符串并返回数字的麻烦。
2021-03-19 05:04:52
@DejayClayton 有什么问题吗?我什至认为这是值得点赞的。
2021-03-26 05:04:52
抱歉,我不知道我实际上在抱怨什么,除了它看起来像一堆无差别的神奇数字。但我想它很简洁。
2021-03-27 05:04:52
例如,如果数字结果为 1.005,则将四舍五入为 1 而不是 1.1。下面的折扣等于 1 而不是 1.1 let price = 98.995 let listprice = 100 var discount = Math.round((100 - (price / listprice) * 100) * 100) / 100;
2021-04-04 05:04:52

我发现的最好和最简单的解决方案是

function round(value, decimals) {
 return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
}   
round(1.005, 2); // 1.01
此解决方案不适用于 JS 已经以字符串形式以科学记数法表示的值。尝试调用 round(0.0000000001, 2) 会得到错误的答案。对于这样一个简单的数学运算,在数字和字符串之间切换两次也是完全愚蠢的
2021-04-01 05:04:52
此解决方案也不适用于typescript
2021-04-01 05:04:52
第一个有效的解决方案!
2021-04-04 05:04:52