如何在JavaScript中像PHP一样进行四舍五入

11

我正在尝试用JavaScript对浮点数进行四舍五入,就像我在PHP中所做的那样; 但是我无法使两种语言以相同的方式舍入以下数字:

6.404999999999999

当我使用PHP round时,我得到:6.41但是当我尝试使用JavaScript进行舍入时,我总是得到6.40

INFO: 正确的答案是https://dev59.com/g1QJ5IYBdhLWcg3wnXV-#54721202

我的JavaScript尝试:

尝试#1:

module.exports = function round (value, precision, mode) {
  var m, f, isHalf, sgn // helper variables
  // making sure precision is integer
  precision |= 0
  m = Math.pow(10, precision)
  value *= m
  // sign of the number
  sgn = (value > 0) | -(value < 0)
  isHalf = value % 1 === 0.5 * sgn
  f = Math.floor(value)

  if (isHalf) {
    switch (mode) {
      case 'PHP_ROUND_HALF_DOWN':
      // rounds .5 toward zero
        value = f + (sgn < 0)
        break
      case 'PHP_ROUND_HALF_EVEN':
      // rouds .5 towards the next even integer
        value = f + (f % 2 * sgn)
        break
      case 'PHP_ROUND_HALF_ODD':
      // rounds .5 towards the next odd integer
        value = f + !(f % 2)
        break
      default:
      // rounds .5 away from zero
        value = f + (sgn > 0)
    }
  }

  return (isHalf ? value : Math.round(value)) / m
}

提取自:http://locutus.io/php/math/round/

尝试 #2:

round(decimal: number, decimalPoints: number): number{
    let roundedValue = Math.round(decimal * Math.pow(10, decimalPoints)) / Math.pow(10, decimalPoints);

    console.log(`Rounded ${decimal} to ${roundedValue}`);
    return roundedValue;
}

来源: https://dev59.com/Smgt5IYBdhLWcg3wwwO-#50918962


我尝试了其他方法,但没有成功。

有人能告诉我如何让JavaScript的四舍五入像PHP一样吗?

你能告诉我为什么它们在我解释的情况下以不同的方式工作吗?


1
这可能是因为PHP没有数字的准确二进制表示,并且知道该数字实际上是6.405,但无法在十进制中准确显示它。这是一个很好的阅读材料,问题在于很可能当您将该数字的十进制表示发送到JavaScript时,准确的二进制表示会丢失,JavaScript必须使用嘈杂的数据进行计算。我怀疑除了将操作发送到JavaScript并让它从头开始计算之外,没有其他事情可做。 - apokryfos
4个回答

4
我认为最好的答案是下面这个:

我认为最佳答案如下:

function roundLikePHP(num, dec){
  var num_sign = num >= 0 ? 1 : -1;
  return parseFloat((Math.round((num * Math.pow(10, dec)) + (num_sign * 0.0001)) / Math.pow(10, dec)).toFixed(dec));
}

我尝试了其他解决方案,使用1.015时并不能按预期工作。

这个解决方案很好地解决了问题,就像PHP中的round函数一样,对我尝试的所有数字都有效。


1
最佳答案!:) 感谢 @tomloprod - Sajjad Ali
虽然这个函数与php函数接近,但在某些情况下仍会返回不同的结果。 例如,roundLikePHP(0.49999,0) = 1,而在php中 round(0.49999) = 0。 - Andyba
@Andyba 你好。这个问题只会在保留0位小数时出现,所以至少在我的情况下,它不会影响我。 - tomloprod
@tomloprod 不完全正确:roundLikePHP(0.004999999,2) = 0.01,而在php中round(0.004999999,2) = 0。 - Andyba

3

你可以使用toPrecision函数。

它将根据提供的 precision 进行四舍五入。这里我使用4进行四舍五入得到 6.405,然后使用3进行四舍五入得到 6.41

parseFloat((6.404999999999999).toPrecision(4)).toPrecision(3);

console.log(parseFloat((6.404999999999999).toPrecision(4)).toPrecision(3));


1
你能解释一下为什么你的解决方案不能处理下一个数字 1.015 吗?这个数字四舍五入后是 1.01 而不是 1.02 - tomloprod

2
您可以像这样做:
function roundToXDigits(value, digits)
{
    if (!digits) {
        digits = 2;
    }

    value = value * Math.pow(10, digits);
    value = Math.round(value);
    value = value / Math.pow(10, digits);

    return value
}

var num = roundToXDigits(6.404999999999999, 3); //creates 6.405

console.log(roundToXDigits(num, 2)); //creates 6.41

问题在于,JavaScript 从技术上讲并没有错。当你四舍五入时,6.4049 变成了 6.405(保留两位小数是 6.40),这就是为什么它不像预期那样工作的原因。你必须运行该函数两次,才能将 405 四舍五入为 4.1。
来源:JavaScript math, round to two decimal places ^^ Bryce 的答案的扩展用法。

treyBake 运行良好!我认为它与 @C2486 的答案类似。各位,你们认为哪种解决方案最好? - tomloprod
@tomloprod:深入探索任何方法总是很好的,但最佳实践是使用语言或框架提供的内置方法。看到toPrecision的详细代码作为roundToXDigits是很好的。如果任何浏览器版本不支持内置方法,那么这个roundToXDigits方法将非常有用。 - Niklesh Raut
1
@treyBake,你能解释一下为什么你的解决方案不能处理下一个数字:1.015吗?它会四舍五入成1.01而不是1.02 - tomloprod
@treyBake 在这个 JSFiddle 中,你可以展示如何用 PHP 显示下一个数字“1.015”时你的函数不起作用:https://jsfiddle.net/u3jefrph/ 无论如何,如果你看一下我的答案(https://dev59.com/g1QJ5IYBdhLWcg3wnXV-#54721202),你会发现我最终实现解决这个问题的方法。 - tomloprod
1
@tomloprod 这个解决方案在1.015版本中不起作用,因为在JS中1.015*100=101.49999999999999。 - Andyba
显示剩余2条评论

1

你可以尝试

console.log(Number(n.toFixed(3)).toFixed(2));

eg.

var n = 6.404999999999999;
console.log(n.toFixed(2)); //=> 6.40
console.log(n.toFixed(3)); //=> 6.405


@RokoC.Buljan,PHP和JavaScript中的round方法存在根本性差异。但是根据round功能的基本定义,这些值等同于JavaScript的结果。 - Chameera
这样怎么样,console.log(Number(n.toFixed(3)).toFixed(2)); - Chameera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接