我想最多四舍五入两位小数,但只有在必要时。

输入:

10
1.7777777
9.1

输出:

10
1.78
9.1

如何在JavaScript中执行此操作?


当前回答

只有在必要时才能实现这种舍入的一种方法是使用Number.protype.toLocaleString():

myNumber.toLocaleString('en', {maximumFractionDigits:2, useGrouping:false})

这将提供您期望的输出,但是是字符串。如果不是您期望的数据类型,您仍然可以将它们转换回数字。

其他回答

这是我解决这个问题的方法:

function roundNumber(number, precision = 0) {
    var num = number.toString().replace(",", "");
    var integer, decimal, significantDigit;

    if (num.indexOf(".") > 0 && num.substring(num.indexOf(".") + 1).length > precision && precision > 0) {
        integer = parseInt(num).toString();
        decimal = num.substring(num.indexOf(".") + 1);
        significantDigit = Number(decimal.substr(precision, 1));

        if (significantDigit >= 5) {
            decimal = (Number(decimal.substr(0, precision)) + 1).toString();
            return integer + "." + decimal;
        } else {
            decimal = (Number(decimal.substr(0, precision)) + 1).toString();
            return integer + "." + decimal;
        }
    }
    else if (num.indexOf(".") > 0) {
        integer = parseInt(num).toString();
        decimal = num.substring(num.indexOf(".") + 1);
        significantDigit = num.substring(num.length - 1, 1);

        if (significantDigit >= 5) {
            decimal = (Number(decimal) + 1).toString();
            return integer + "." + decimal;
        } else {
            return integer + "." + decimal;
        }
    }

    return number;
}

另一种方法是:

number = 16.6666666;
console.log(parseFloat(number.toFixed(2)));
"16.67"

number = 16.6;
console.log(parseFloat(number.toFixed(2)));
"16.6"

number = 16;
console.log(parseFloat(number.toFixed(2)));
"16"

.toFixed(2)返回一个正好有两个小数点的字符串,可以是尾随零,也可以不是尾随零。执行parseFloat()将消除那些尾随的零。

要在小数位置pos(不包括小数)舍入,请执行Math.rround(num*Math.pow(10,pos))/Math.pow(1,pos

var控制台={日志:函数{document.getElementById(“控制台”).innerHTML+=s+“<br/>”}}var roundDecimals=函数(num,pos){return(Math.round(num*Math.pow(10,pos))/Math.pop(10,pos));}//https://en.wikipedia.org/wiki/Pivar pi=3.14159265358979323846264338327950288419716939937510;对于(var i=2;i<15;i++)console.log(“pi=”+roundDecimals(pi,i));对于(var i=15;i>=0;--i)console.log(“pi=”+roundDecimals(pi,i));<div id=“console”/>

从我在MDN上找到的precisionRound(1.005的事件返回1而不是1.01)上提出的示例开始,我编写了一个自定义precisionRound,用于管理随机精度数,1.005返回1.01。

这是一个函数:

function precisionRound(number, precision)
{
  if(precision < 0)
  {
    var factor = Math.pow(10, precision);
    return Math.round(number * factor) / factor;
  }
  else
    return +(Math.round(number + "e+"+precision)  + "e-"+precision);
}

console.log(precisionRound(1234.5678, 1));  // output: 1234.6
console.log(precisionRound(1234.5678, -1)); // output: 1230
console.log(precisionRound(1.005, 2));      // output: 1.01
console.log(precisionRound(1.0005, 2));     // output: 1
console.log(precisionRound(1.0005, 3));     // output: 1.001
console.log(precisionRound(1.0005, 4));     // output: 1.0005

对于TypeScript:

public static precisionRound(number: number, precision: number)
{
  if (precision < 0)
  {
    let factor = Math.pow(10, precision);
    return Math.round(number * factor) / factor;
  }
  else
    return +(Math.round(Number(number + "e+" + precision)) +
      "e-" + precision);
}

您应该使用:

Math.round( num * 100 + Number.EPSILON ) / 100

似乎没有人知道数字EPSILON。

此外,值得注意的是,这并不像某些人所说的那样是JavaScript的怪异之处。

这就是浮点数在计算机中的工作方式。与99%的编程语言一样,JavaScript没有自制的浮点数;它依赖于CPU/FPU。计算机使用二进制,在二进制中,没有像0.1这样的数字,而只是二进制的近似值。为什么?出于同样的原因,1/3不能用十进制写:它的值是0.33333333……无穷大为三。

这里是Number.EPSILON。这个数字是1和双精度浮点数字中存在的下一个数字之间的差值。就是这样:在1和1+number.EPSILON之间没有数字。

编辑:

正如评论中所问的,让我们澄清一件事:添加Number.EPSILON仅当要舍入的值是算术运算的结果时才相关,因为它可以吞下一些浮点误差增量。

当值来自直接来源(例如:文字、用户输入或传感器)时,它不起作用。

编辑(2019):

像@maganap和一些人指出的那样,最好在相乘之前加上Number.EPSILON:

Math.round( ( num + Number.EPSILON ) * 100 ) / 100

编辑(2019年12月):

最近,我使用了一个类似于此的函数来比较epsilon感知的数字:

const ESPILON_RATE = 1 + Number.EPSILON ;
const ESPILON_ZERO = Number.MIN_VALUE ;

function epsilonEquals( a , b ) {
  if ( Number.isNaN( a ) || Number.isNaN( b ) ) {
    return false ;
  }
  if ( a === 0 || b === 0 ) {
    return a <= b + EPSILON_ZERO && b <= a + EPSILON_ZERO ;
  }
  return a <= b * EPSILON_RATE && b <= a * EPSILON_RATE ;
}

我的用例是我多年来开发的断言+数据验证库。

事实上,在代码中,我使用的是ESPILON_RATE=1+4*数字.EPSILON和EPSILON_ZERO=4*数字.MIN_VALUE(四倍于EPSILON),因为我想要一个足够宽松的等式检查器来累积浮点错误。

到目前为止,它看起来很适合我。我希望这会有所帮助。