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

输入:

10
1.7777777
9.1

输出:

10
1.78
9.1

如何在JavaScript中执行此操作?


当前回答

您应该使用:

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),因为我想要一个足够宽松的等式检查器来累积浮点错误。

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

其他回答

另一种方法是:

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()将消除那些尾随的零。

这是astorije的答案的修改版本,更好地支持负值舍入。

// https://stackoverflow.com/a/21323513/384884
// Modified answer from astorije
function round(value, precision) {
    // Ensure precision exists
    if (typeof precision === "undefined" || +precision === 0) {
        // Just do a regular Math.round
        return Math.round(value);
    }

    // Convert the value and precision variables both to numbers
    value = +value;
    precision = +precision;

    // Ensure the value is a number and that precision is usable
    if (isNaN(value) || !(typeof precision === "number" && precision % 1 === 0)) {
        // Return NaN
        return NaN;
    }

    // Get the sign of value
    var signValue = Math.sign(value);

    // Get the absolute value of value
    value = Math.abs(value);

    // Shift
    value = value.toString().split("e");
    value = Math.round(+(value[0] + "e" + (value[1] ? (+value[1] + precision) : precision)));

    // Shift back
    value = value.toString().split("e");
    value = +(value[0] + "e" + (value[1] ? (+value[1] - precision) : -precision));

    // Apply the sign
    value = value * signValue;

    // Return rounded value
    return value;
}

下面是一个原型方法:

Number.prototype.round = function(places){
    places = Math.pow(10, places); 
    return Math.round(this * places)/places;
}

var yournum = 10.55555;
yournum = yournum.round(2);

对我来说,Math.rround()没有给出正确的答案。我发现Fixed(2)效果更好。以下是两者的示例:

console.log(数学舍入(43000/80000)*100);//错误的答案console.log(((43000/80000)*100).toFixed(2));//正确回答

根据评论中已给出的答案,链接至http://jsfiddle.net/AsRqx/,下面的一个对我来说很好。

function C(num)
{
    return +(Math.round(num + "e+2") + "e-2");
}

function N(num, places)
{
    return +(Math.round(num + "e+" + places) + "e-" + places);
}

C(1.005);

N(1.005, 0);
N(1.005, 1); // Up to 1 decimal places
N(1.005, 2); // Up to 2 decimal places
N(1.005, 3); // Up to 3 decimal places