舍入到最多2位小数(仅在必要时)

sti*_*man 2492 javascript decimal decimal-point rounding

我想最多舍入2位小数,但只在必要时.

输入:

10
1.7777777
9.1
Run Code Online (Sandbox Code Playgroud)

输出:

10
1.78
9.1
Run Code Online (Sandbox Code Playgroud)

我怎么能这样做__CODE__

Bri*_*tas 3124

使用 Math.round(num * 100) / 100

  • 虽然这适用于大多数情况,但它不适用于1.005,最终会变为1而不是1.01 (372认同)
  • 一个简单的解决方法.对于2 dp,使用`Math.round((num + 0.00001)*100)/ 100`.尝试`Math.round((1.005 + 0.00001)*100)/ 100`和`Math.round((1.0049 + 0.00001)*100)/ 100` (144认同)
  • 对于那些没有得到它的人来说,这种技术称为缩放.基本上这里的答案是将小数点上的两个数字转换成一个整数,以避免所有疯狂的浮点问题,然后将其转换回原来的数除以100,你得到了回答2dp. (81认同)
  • @James哇,这真的很奇怪 - 我在Chrome开发控制台工作,我注意到1.005*100 = 100.49999999999999.Math.round(100.49999999999999)的计算结果为100,而Math.round(100.5)的计算结果为101. IE9的功能相同.这是由于[javascript中的浮点怪异](http://stackoverflow.com/questions/588004/is-javascripts-floating-point-math-broken) (76认同)
  • @mrkschan为什么这样做,并且所有数字都是万无一失的? (30认同)
  • 我发现 10.075 的舍入错误。即使进行了 epsilon 修复,也给出 10.07 而不是 10.08。 (24认同)
  • Math.round((519.805+ Number.EPSILON) * 100) / 100,四舍五入为 519.8 (15认同)
  • 截至18年2月,这个问题有44个问题,其中有数千个赞成票,但每个都有一个"这是错误的,不起作用......"的评论.社区驱动的方法在这种情况下不起作用.有没有一个库可以解决这个问题? (7认同)
  • @CMCDragonkai,我提到的解决方法对于所有数字并非万无一失,它只能达到3 dp (4认同)
  • 令人惊讶的是,这个错误的答案得到了如此多的支持。以下是更好的答案:/sf/answers/2047449421/ (4认同)
  • 很有趣的是,这种方法也适用于舍入到任何最近的分数,例如四分之一:`Math.round(num*4)/ 4` (3认同)
  • @PSatishPatro(我假设你的意思是说 224.99 而不是 224.95)。如果您四舍五入到小数点后第二位(百分之一),那么我们应该只关心小数点后第三位(千分位)是多少,之后的所有数字都会被删除。因此,从输入 224.98499999 来看,只有 224.984 重要,这意味着 **224.98** 是正确的。 (3认同)
  • Math.round(1.255 * 100) / 100 将是 1.25 。这是不对的 (3认同)
  • @PSatishPatro,我意识到我们偏离了主题,但将 224.9849 四舍五入到小数点后两位应该,无论用任何语言或手工,结果都是 224.98。如果你得到 224.99 恐怕你做错了。最简单的思考方法是寻找最接近的只有两位小数的数字。虽然差别不大,但 224.9849 更接近 224.98,而不是 224.99。 (3认同)
  • 会亲自说“ Math.ceil(num * 100)/ 100”,因为回合在0.5边距上起作用,低于0.5则变为0,高于0.5则变为1,这似乎不是要求的 (2认同)
  • @James r(r(1000*1.005)/ 10)/ 100其中r = Math.round将始终有效:) (2认同)
  • 尽管如此,但正如许多人指出的那样,由于浮点问题,它有一些警告.我更喜欢@VicJordan的答案,使用`.toFixed(2)`/sf/answers/3503959861/ (2认同)
  • 尽管此答案简单而优雅,但并不可靠,但注释中提到了一些反例。应该修改答案,以使每个读者都明白这一点。否则,许多人将在不知情的情况下使用不可靠的代码。并非所有人都阅读了数千封支持的答案的评论。 (2认同)
  • 不知道为什么这被标记为正确答案。它实际上无法正常工作 (2认同)
  • `Math.round((num + Number.EPSILON) * 100) / 100` 在某些情况下,当您对 1.3549999999999998 这样的数字进行舍入时,它将返回不正确的结果。应该是 1.35,但结果是 1.36。参考:/sf/answers/898131811/ (2认同)
  • 这是行不通的,也不可能行得通。浮点值没有小数位,它们有二进制位,并且两者是不可通约的。 (2认同)
  • 正如 @Amr Ali 在这里提到的 /sf/answers/3413510551/,使用此方法可以获得的最佳结果是在舍入之前乘以 Number.EPSILON: `Math.round((value * 100 ) * (1 + Number.EPSILON)) / 100` - 这也可以很好地处理开箱即用的负值 (2认同)

A K*_*nin 2887

如果值是文本类型:

parseFloat("123.456").toFixed(2);
Run Code Online (Sandbox Code Playgroud)

如果值是数字:

var numb = 123.23454;
numb = numb.toFixed(2);
Run Code Online (Sandbox Code Playgroud)

有一个缺点,像1.5这样的值会给出"1.50"作为输出.@minitech建议修复:

var numb = 1.5;
numb = +numb.toFixed(2);
// Note the plus sign that drops any "extra" zeroes at the end.
// It changes the result (which is a string) into a number again (think "0 + foo"),
// which means that it uses only as many digits as necessary.
Run Code Online (Sandbox Code Playgroud)

这似乎Math.round是一个更好的解决方案.但事实并非如此!在某些情况下,它不会正确圆:

Math.round(1.005 * 1000)/1000 // Returns 1 instead of expected 1.01!
Run Code Online (Sandbox Code Playgroud)

在某些情况下,toFixed()也不会正确舍入(在Chrome v.55.0.2883.87中测试)!

例子:

parseFloat("1.555").toFixed(2); // Returns 1.55 instead of 1.56.
parseFloat("1.5550").toFixed(2); // Returns 1.55 instead of 1.56.
// However, it will return correct result if you round 1.5551.
parseFloat("1.5551").toFixed(2); // Returns 1.56 as expected.

1.3555.toFixed(3) // Returns 1.355 instead of expected 1.356.
// However, it will return correct result if you round 1.35551.
1.35551.toFixed(2); // Returns 1.36 as expected.
Run Code Online (Sandbox Code Playgroud)

我想,这是因为1.555实际上就像浮动1.55499994幕后.

解决方案1是使用具有所需舍入算法的脚本,例如:

function roundNumber(num, scale) {
  if(!("" + num).includes("e")) {
    return +(Math.round(num + "e+" + scale)  + "e-" + scale);
  } else {
    var arr = ("" + num).split("e");
    var sig = ""
    if(+arr[1] + scale > 0) {
      sig = "+";
    }
    return +(Math.round(+arr[0] + "e" + sig + (+arr[1] + scale)) + "e-" + scale);
  }
}
Run Code Online (Sandbox Code Playgroud)

https://plnkr.co/edit/uau8BlS1cqbvWPCHJeOy?p=preview

解决方案2是避免前端计算并从后端服务器中提取舍入值.

  • 这个(toFixed)方法很好,并为我工作,但它特别*不符合"仅在必要时"的原始要求.(它绕1.5到1.50,这打破了规范.) (78认同)
  • `parseFloat("55.555").toFixed(2)`在Chrome开发控制台中返回"55.55". (34认同)
  • 对于"必要时"的要求,请执行以下操作:`parseFloat(number.toFixed(decimalPlaces));`@PerLundberg (25认同)
  • 使用toFixed而不是Math.round没有任何优势; toFixed导致完全相同的舍入问题(尝试使用5.555和1.005),但是比500.(没有开玩笑)慢于Math.round ...似乎@MarkG答案在这里更准确. (20认同)
  • toFixed不"有时"返回一个字符串,它总是返回一个字符串. (14认同)
  • 这似乎行不通.例如`+(1.005).toFixed(2)`给出`1`而不是1.01 (4认同)
  • 您应该使用“Number(a)”、“parseFloat(a)”(实际上行为相同的 /sf/answers/839202871/),而不是“eval(a)”。您甚至可以只使用“+a”。我更喜欢“数字(a)”。 (4认同)
  • 与乌斯塔斯的建议相同的问题。10.075 输入 = 10.07 输出。不好。 (4认同)
  • `roundNumber(1.4449,2)`当它应该返回1.44`时返回`1.45` (2认同)
  • 这是所有要点的更正确答案。 (2认同)
  • 特别喜欢 @minitech 的小技巧,以避免不必要的小数 (numb = numb.toFixed(2);) (2认同)

Mar*_*rkG 429

您可以使用

function roundToTwo(num) {    
    return +(Math.round(num + "e+2")  + "e-2");
}
Run Code Online (Sandbox Code Playgroud)

我在MDN上发现了这个.他们的方式避免了提到的 1.005的问题.

roundToTwo(1.005)
1.01
roundToTwo(10)
10
roundToTwo(1.7777777)
1.78
roundToTwo(9.1)
9.1
roundToTwo(1234.5678)
1234.57
Run Code Online (Sandbox Code Playgroud)

  • 请注意,对于会产生NaN的大而小的浮子,例如+"1e-21 + 2"将无法正确解析. (39认同)
  • 在`1.0049999999999999`和`1.005`之间没有(浮点)数字,因此根据定义,它们是相同的数字.这被称为dedekind cut. (31认同)
  • 你已经解决了'1.005'问题',但引入了一个新问题:现在,在Chrome控制台中,`roundToTwo(1.0049999999999999)`出现为1.01(不可避免地,因为`1.0049999999999999 == 1.005`).在我看来,如果你输入`num = 1.005`',你得到的浮点数''应该'舍入到1.00,因为num的确切值小于1.005.当然,在我看来,字符串'1.005''显然''应该'舍入到1.01.事实上,不同的人似乎对这里的实际正确行为有不同的直觉,这是其复杂性的部分原因. (14认同)
  • @Redsandro,`+(val)`是使用`Number(val)`的强制等价物.将"e-2"连接到一个数字会产生一个需要转换回数字的字符串. (11认同)
  • @Azmisov是对的.当`1.00499 <1.005`为'true`时,`1.0049999999999999 <1.005`评估为'false`. (5认同)
  • @AntonBabushkin**尾随零是一个输出问题**,而不是舍入问题.**舍入**后,你可以使用`.Fif(2)`来输出至少两位小数. (4认同)
  • 这是正确处理所有案例的唯一答案.它可以被重写:`return +(Math.round(number +"e +"+ precision)+"e-"+ precision);`注意:对于负数,则向0舍入.例如round(-1835.665,2)结果:-1835.66 (4认同)
  • 这对于负数不太适用。 (4认同)
  • 用 e 传递一个数字,它返回 NaN,例如 1.19e-7 (3认同)
  • 但是,如果 num 为 `-2.9e-7`,则 `+(Math.round(num + "e+2") + "e-2") ` 返回 `NaN`,这不是所需的结果。至少在 Chrome 101 上 (2认同)
  • 如果 -1.005 =&gt; -1(不带小数) (2认同)

Lav*_*tis 140

MarkG的答案是正确的.这是任意数量小数位的通用扩展名.

Number.prototype.round = function(places) {
  return +(Math.round(this + "e+" + places)  + "e-" + places);
}
Run Code Online (Sandbox Code Playgroud)

用法:

var n = 1.7777;    
n.round(2); // 1.78
Run Code Online (Sandbox Code Playgroud)

单元测试:

it.only('should round floats to 2 places', function() {

  var cases = [
    { n: 10,      e: 10,    p:2 },
    { n: 1.7777,  e: 1.78,  p:2 },
    { n: 1.005,   e: 1.01,  p:2 },
    { n: 1.005,   e: 1,     p:0 },
    { n: 1.77777, e: 1.8,   p:1 }
  ]

  cases.forEach(function(testCase) {
    var r = testCase.n.round(testCase.p);
    assert.equal(r, testCase.e, 'didn\'t get right number');
  });
})
Run Code Online (Sandbox Code Playgroud)

  • 皮尔在MarkG的回答中提出了一个严重的问题. (20认同)
  • 哦,来吧,不要修改原型 (14认同)
  • 注意:如果你不想改变Number.prototype - 只需将其写为函数:`function round(number,decimals){return +(Math.round(number +"e +"+ decimals)+"e - "+小数"; }` (8认同)
  • 尝试n:1e + 19-返回NaN (3认同)
  • 该算法总是向上舍入(而不是从零开始).因此,在负数的情况下,输出不是您所期望的:`( - 1.005).round(2)=== -1` (3认同)
  • 扩展此功能的好方法。您可以检查十进制是否为负,然后将e +和e-反转。那么n = 115; n.round(-2); 会产生100 (2认同)
  • 如果输入数字已经是指数形式怎么办?你会得到NaN (2认同)
  • 为了适应非常小和非常大的数字,这些数字将自动呈指数形式,您可以使用 toFixed 解决这个问题。即 `function round(val,decimals) { return +(Math.round(+(val.toFixed(decimals) + "e+" + 小数点)) + "e-" + 小数点); }` (2认同)

cro*_*vel 85

你应该使用:

Math.round( num * 100 + Number.EPSILON ) / 100
Run Code Online (Sandbox Code Playgroud)

似乎没有人知道Number.EPSILON.

另外值得注意的是,这并不是像某些人所说的JavaScript怪异.

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

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

编辑:

正如评论中所要求的那样,让我们​​澄清一件事:Number.EPSILON只有当round的值是算术运算的结果时才添加,因为它可以吞下一些浮点误差delta.

当值来自直接源(例如:文字,用户输入或传感器)时,它没有用.

  • 实际上,你必须在乘以100之前添加epsilon.`Math.round((num + Number.EPSILON)*100)/ 100`.我同意这也是正确舍入的正确方法(尽管这不是这个问题中的问题). (18认同)
  • 这是正确的答案!问题本身与浮点数在内部的工作方式有关,而不与javascript有关 (3认同)

Gou*_*gla 80

一个人可以使用.toFixed(NumberOfDecimalPlaces).

var str = 10.234.toFixed(2); // => '10.23'
var number = Number(str); // => 10.23
Run Code Online (Sandbox Code Playgroud)

  • 还因为它添加了尾随零,这不是原始问题所要求的*. (4认同)
  • @ChadMcElligott:您的正则表达式不适用于整数:`Number(9).toFixed(2).replace(/ 0 + $ /,'')`=&gt;“ 9”。 (3认同)
  • 但是尾随零很容易用正则表达式去掉,即`Number(10.10000.toFixed(2).replace(/ 0 + $ /,''))`=> 10.1 (2认同)
  • 这是[user3711536的答案](/sf/ask/828304011/#24406175)的重复项 - 不过同样没有任何解释或文档链接。至少另一个答案有更多的样本输入和输出。 (2认同)

Ace*_*ban 70

考虑.toFixed().toPrecision():

http://www.javascriptkit.com/javatutors/formatnumber.shtml

  • 这两个都没用 (13认同)
  • http://stackoverflow.com/questions/566564/javascript-functions-math-roundnum-vs-num-tofixed0-and-browser-inconsistenci (2认同)

Mar*_*ery 69

这个问题很复杂.

假设我们有一个函数,roundTo2DP(num)它将float作为参数并返回一个舍入到2位小数的值.每个表达式应该评估什么?

  • roundTo2DP(0.014999999999999999)
  • roundTo2DP(0.0150000000000000001)
  • roundTo2DP(0.015)

"显而易见"的答案是第一个例子应该舍入到0.01(因为它接近0.01而不是0.02),而另外两个应该舍入到0.02(因为0.0150000000000000001接近0.02而不是0.01,因为0.015恰好在中间他们并且有一个数学约定,这些数字被四舍五入).

您可能已经猜到的问题是,roundTo2DP 无法实现这些明显的答案,因为传递给它的所有三个数字都是相同的数字.IEEE 754二进制浮点数(JavaScript使用的类型)不能精确地表示大多数非整数数字,因此上面的所有三个数字文字都会四舍五入到附近的有效浮点数.事实上,这个数字正是如此

0.01499999999999999944488848768742172978818416595458984375

它接近0.01而不是0.02.

您可以在浏览器控制台,Node shell或其他JavaScript解释器中看到所有三个数字相同.只是比较它们:

> 0.014999999999999999 === 0.0150000000000000001
true
Run Code Online (Sandbox Code Playgroud)

因此,当我写作时m = 0.0150000000000000001,我最终得到的确切值m更接近于0.010.02.然而,如果我转换m为String ...

> var m = 0.0150000000000000001;
> console.log(String(m));
0.015
> var m = 0.014999999999999999;
> console.log(String(m));
0.015
Run Code Online (Sandbox Code Playgroud)

...我得到0.015,它应该舍入到0.02,这显然不是我之前说过的所有这些数字完全相等的56位小数位数.那么黑暗魔法是什么呢?

答案可以在ECMAScript规范的7.1.12.1节中找到:ToString应用于Number类型.这里规定了将一些数字m转换为字符串的规则.关键部分是第5点,其中生成一个整数s,其数字将用于m的字符串表示:

Ñ,ķ,和小号是整数,使得ķ ≥1,10 ķ -1小号 <10 ķ,为对数的值小号 ×10 ñ - ķ,并且ķ是尽可能小.注意,k是s的十进制表示中的位数,s不能被10整除,并且s的最低有效位不一定由这些标准唯一确定.

这里的关键部分是要求" k尽可能小".该要求相当于一个要求,给定一个数字m,String(m)必须具有最小可能的位数,同时仍满足要求Number(String(m)) === m.既然我们已经知道,0.015 === 0.0150000000000000001现在已经清楚为什么String(0.0150000000000000001) === '0.015'必须如此.

当然,这些讨论都没有直接回答roundTo2DP(m) 应该返回的内容.如果m确切的值是0.01499999999999999944488848768742172978818416595458984375,但它的字符串表示是'0.015',那么当我们将它舍入到两个小数位时,什么是正确的答案 - 数学,实际,哲学或其他什么?

对此没有一个正确的答案.这取决于您的用例.在下列情况下,您可能希望尊重String表示并向上舍入:

  • 所表示的价值本质上是离散的,例如像第纳尔一样的三位小数货币的货币数量.在这种情况下,像0.015这样的Number 的 0.015,而它在二进制浮点中获得的0.0149999999 ...表示是舍入误差.(当然,许多人会合理地争辩说,你应该使用十进制库来处理这些值,并且从不将它们首先表示为二进制浮点数.)
  • 该值由用户键入.在这种情况下,再次输入的确切十进制数比最近的二进制浮点表示更"真".

另一方面,当您的值来自固有的连续标度时,您可能希望尊重二进制浮点值并向下舍入 - 例如,如果它是来自传感器的读数.

这两种方法需要不同的代码.为了尊重Number的String表示,我们可以(通过相当多一些相当微妙的代码)实现我们自己的舍入,它直接作用于String表示,逐位,使用您在学校时使用的相同算法被教导如何围绕数字.下面是一个例子,它尊重OP要求通过在小数点后剥去尾随零来"仅在必要时"将数字表示为2位小数的要求; 当然,您可能需要根据您的确切需求进行调整.

/**
 * Converts num to a decimal string (if it isn't one already) and then rounds it
 * to at most dp decimal places.
 *
 * For explanation of why you'd want to perform rounding operations on a String
 * rather than a Number, see http://stackoverflow.com/a/38676273/1709587
 *
 * @param {(number|string)} num
 * @param {number} dp
 * @return {string}
 */
function roundStringNumberWithoutTrailingZeroes (num, dp) {
    if (arguments.length != 2) throw new Error("2 arguments required");

    num = String(num);
    if (num.indexOf('e+') != -1) {
        // Can't round numbers this large because their string representation
        // contains an exponent, like 9.99e+37
        throw new Error("num too large");
    }
    if (num.indexOf('.') == -1) {
        // Nothing to do
        return num;
    }

    var parts = num.split('.'),
        beforePoint = parts[0],
        afterPoint = parts[1],
        shouldRoundUp = afterPoint[dp] >= 5,
        finalNumber;

    afterPoint = afterPoint.slice(0, dp);
    if (!shouldRoundUp) {
        finalNumber = beforePoint + '.' + afterPoint;
    } else if (/^9+$/.test(afterPoint)) {
        // If we need to round up a number like 1.9999, increment the integer
        // before the decimal point and discard the fractional part.
        finalNumber = Number(beforePoint)+1;
    } else {
        // Starting from the last digit, increment digits until we find one
        // that is not 9, then stop
        var i = dp-1;
        while (true) {
            if (afterPoint[i] == '9') {
                afterPoint = afterPoint.substr(0, i) +
                             '0' +
                             afterPoint.substr(i+1);
                i--;
            } else {
                afterPoint = afterPoint.substr(0, i) +
                             (Number(afterPoint[i]) + 1) +
                             afterPoint.substr(i+1);
                break;
            }
        }

        finalNumber = beforePoint + '.' + afterPoint;
    }

    // Remove trailing zeroes from fractional part before returning
    return finalNumber.replace(/0+$/, '')
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

> roundStringNumberWithoutTrailingZeroes(1.6, 2)
'1.6'
> roundStringNumberWithoutTrailingZeroes(10000, 2)
'10000'
> roundStringNumberWithoutTrailingZeroes(0.015, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.015000', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(1, 1)
'1'
> roundStringNumberWithoutTrailingZeroes('0.015', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(0.01499999999999999944488848768742172978818416595458984375, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.01499999999999999944488848768742172978818416595458984375', 2)
'0.01'
Run Code Online (Sandbox Code Playgroud)

上面的函数可能就是你想要用来避免用户看到他们输入的数字被错误舍入的内容.

(作为替代方案,您也可以尝试使用round10库,该库提供类似行为的函数,具有完全不同的实现.)

但是,如果你有第二种数字 - 从连续尺度中取得的值,那么没有理由认为具有较少小数位的近似十进制表示比具有更多数字的数字更准确?在这种情况下,我们希望尊重String表示,因为该表示(如规范中所述)已经是排序的; 我们不想错误地说"0.014999999 ... 375轮到0.015,最高为0.02,所以0.014999999 ...... 375轮到0.02".

在这里,我们可以简单地使用内置toFixed方法.请注意,通过调用Number()返回的String toFixed,我们得到一个Number,其String表示没有尾随零(由于JavaScript计算数字的String表示的方式,在本回答前面讨论过).

/**
 * Takes a float and rounds it to at most dp decimal places. For example
 *
 *     roundFloatNumberWithoutTrailingZeroes(1.2345, 3)
 *
 * returns 1.234
 *
 * Note that since this treats the value passed to it as a floating point
 * number, it will have counterintuitive results in some cases. For instance,
 * 
 *     roundFloatNumberWithoutTrailingZeroes(0.015, 2)
 *
 * gives 0.01 where 0.02 might be expected. For an explanation of why, see
 * http://stackoverflow.com/a/38676273/1709587. You may want to consider using the
 * roundStringNumberWithoutTrailingZeroes function there instead.
 *
 * @param {number} num
 * @param {number} dp
 * @return {number}
 */
function roundFloatNumberWithoutTrailingZeroes (num, dp) {
    var numToFixedDp = Number(num).toFixed(dp);
    return Number(numToFixedDp);
}
Run Code Online (Sandbox Code Playgroud)

  • @ Dr.GianluigiZaneZanettini *“我有道理吗?” *-不;舍入不是这样的。1.000005以5结尾,但如果四舍五入为最接近的整数,则答案应为1,而不是2。同样,1499995以5结尾,但舍入为最接近的百万,结果应为1000000,而不是2000000。对于362.42499999999995如果四舍五入为2 DP,则应确定四舍五入的方向是*小数点后第三位*,即4。 (2认同)

use*_*ser 62

精确的舍入方法.资料来源:Mozilla

(function(){

    /**
     * Decimal adjustment of a number.
     *
     * @param   {String}    type    The type of adjustment.
     * @param   {Number}    value   The number.
     * @param   {Integer}   exp     The exponent (the 10 logarithm of the adjustment base).
     * @returns {Number}            The adjusted value.
     */
    function decimalAdjust(type, value, exp) {
        // If the exp is undefined or zero...
        if (typeof exp === 'undefined' || +exp === 0) {
            return Math[type](value);
        }
        value = +value;
        exp = +exp;
        // If the value is not a number or the exp is not an integer...
        if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
            return NaN;
        }
        // Shift
        value = value.toString().split('e');
        value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
        // Shift back
        value = value.toString().split('e');
        return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
    }

    // Decimal round
    if (!Math.round10) {
        Math.round10 = function(value, exp) {
            return decimalAdjust('round', value, exp);
        };
    }
    // Decimal floor
    if (!Math.floor10) {
        Math.floor10 = function(value, exp) {
            return decimalAdjust('floor', value, exp);
        };
    }
    // Decimal ceil
    if (!Math.ceil10) {
        Math.ceil10 = function(value, exp) {
            return decimalAdjust('ceil', value, exp);
        };
    }
})();
Run Code Online (Sandbox Code Playgroud)

例子:

// Round
Math.round10(55.55, -1); // 55.6
Math.round10(55.549, -1); // 55.5
Math.round10(55, 1); // 60
Math.round10(54.9, 1); // 50
Math.round10(-55.55, -1); // -55.5
Math.round10(-55.551, -1); // -55.6
Math.round10(-55, 1); // -50
Math.round10(-55.1, 1); // -60
Math.round10(1.005, -2); // 1.01 -- compare this with Math.round(1.005*100)/100 above
// Floor
Math.floor10(55.59, -1); // 55.5
Math.floor10(59, 1); // 50
Math.floor10(-55.51, -1); // -55.6
Math.floor10(-51, 1); // -60
// Ceil
Math.ceil10(55.51, -1); // 55.6
Math.ceil10(51, 1); // 60
Math.ceil10(-55.59, -1); // -55.5
Math.ceil10(-59, 1); // -50
Run Code Online (Sandbox Code Playgroud)

  • @Matija,从数学的角度来看,3544.5249舍入是3544.52,而不是3544.53,所以这段代码是正确的.如果你想要它在这个四舍五入到3544.53和这样的情况(即使很难是不正确的),做这样的事情:`number + = 0.00011` (3认同)

mac*_*ict 59

这里找到的答案都不正确.@stinkycheeseman要求围捕,你们四舍五入.

要整理,请使用:

Math.ceil(num * 100)/100;
Run Code Online (Sandbox Code Playgroud)

  • 示例输入和输出显示,尽管问题是"向上...",但它实际上是为了"圆到......". (14认同)
  • 在测试`Math.ceil(1.1*100)/ 100时发现奇怪的错误;​​`-it返回`1.11`,因为根据全新的现代浏览器Firefox,Chrome,Safari和Opera,1.1*100是'110.00000000000001` ... IE以旧的方式,仍然认为`1.1*100 = 1100`. (8认同)
  • @stinkycheeseman指出了一个特定情况下的错误,他不想总是像ceil一样向上舍入,他只想要0.005来舍入到0.01 (2认同)
  • 大多数值都会返回不正确的结果。尝试一下。 (2认同)

Jay*_*yDM 46

这是一个简单的方法:

Math.round(value * 100) / 100
Run Code Online (Sandbox Code Playgroud)

您可能希望继续执行单独的功能来为您执行此操作:

function roundToTwo(value) {
    return(Math.round(value * 100) / 100);
}
Run Code Online (Sandbox Code Playgroud)

然后你只需传入值.

您可以通过添加第二个参数来增强它以舍入到任意数量的小数.

function myRound(value, places) {
    var multiplier = Math.pow(10, places);

    return (Math.round(value * multiplier) / multiplier);
}
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案有误,请参阅http://stackoverflow.com/questions/38322372/jquery-round-off-money-currency-to-2-decimals/38369867#38369867如果您输入156893.145并使用上述函数对其进行舍入,则得到156893.14而不是156893.15 !!! (2认同)

小智 36

+(10).toFixed(2); // = 10
+(10.12345).toFixed(2); // = 10.12

(10).toFixed(2); // = 10.00
(10.12345).toFixed(2); // = 10.12
Run Code Online (Sandbox Code Playgroud)


Vik*_*ngh 36

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

console.log(Math.round(43000 / 80000) * 100); // wrong answer

console.log(((43000 / 80000) * 100).toFixed(2)); // correct answer
Run Code Online (Sandbox Code Playgroud)

  • 同样重要的是要注意.toFIxed()输出一个字符串,而不是一个数字. (6认同)

小智 35

使用此功能 Number(x).toFixed(2);

  • 如果你不希望它以字符串形式返回,请将它全部包装在`Number`中:`Number(Number(x).toFixed(2));` (8认同)
  • `Number`调用不是必需的,`x.toFixed(2)`有效. (5认同)
  • @bgusach需要进行数字调用,因为语句x.toFixed(2)返回字符串而不是数字。要再次转换为数字,我们需要用数字换行 (3认同)
  • 使用此方法时,`(1).toFixed(2)` 返回`1.00`,但在这种情况下提问者需要`1`。 (2认同)
  • 这是行不通的,`1.005.toFixed(2)` 会产生 `"1"`,而它应该是 `"1.01"`。 (2认同)

pet*_*ner 32

尝试这个轻量级解决方案:

function round(x, digits){
  return parseFloat(x.toFixed(digits))
}

 round(1.222,  2) ;
 // 1.22
 round(1.222, 10) ;
 // 1.222
Run Code Online (Sandbox Code Playgroud)

  • 这个答案与本页提到的问题几次相同.尝试`round(1.005,2)`并看到`1`而不是`1.01`的结果. (4认同)

per*_*mon 32

2017
只需使用本机代码.toFixed()

number = 1.2345;
number.toFixed(2) // "1.23"
Run Code Online (Sandbox Code Playgroud)

如果您需要严格并且只在需要时添加数字,它可以使用 replace

number = 1; // "1"
number.toFixed(5).replace(/\.?0*$/g,'');
Run Code Online (Sandbox Code Playgroud)

  • toFixed方法返回一个字符串.如果你想要一个数字结果,你需要将toFixed的结果发送到parseFloat. (3认同)
  • -1; 不仅在你之前多年的答案提出了"toFixed",而且它不能满足问题中"只在必要时"的条件; `(1).toFixed(2)`给`"1.00"`提问者想要"1". (2认同)

小智 32

另一个简单的解决方案(无需编写任何函数)可以使用 toFixed() 然后再次转换为 float:

例如:

var objNumber = 1201203.1256546456;
objNumber = parseFloat(objNumber.toFixed(2))
Run Code Online (Sandbox Code Playgroud)

  • 不会。仅对高于 (0).5 的值进行四舍五入。 (4认同)

sta*_*005 28

有几种方法可以做到这一点.像我这样的人,Lodash的变种

function round(number, precision) {
    var pair = (number + 'e').split('e')
    var value = Math.round(pair[0] + 'e' + (+pair[1] + precision))
    pair = (value + 'e').split('e')
    return +(pair[0] + 'e' + (+pair[1] - precision))
}
Run Code Online (Sandbox Code Playgroud)

用法:

round(0.015, 2) // 0.02
round(1.005, 2) // 1.01
Run Code Online (Sandbox Code Playgroud)

如果你的项目使用jQuery或lodash,你也可以round在库中找到合适的方法.

更新1

我删除了变体n.toFixed(2),因为它不正确.谢谢@ avalanche1


Mad*_*eep 24

如果您使用的是lodash库,则可以使用lodash的圆形方法,如下所示.

_.round(number, precision)
Run Code Online (Sandbox Code Playgroud)

例如:

_.round(1.7777777, 2) = 1.78
Run Code Online (Sandbox Code Playgroud)

  • 我接受您的观点,即使用 lodash 存在性能缺陷。我认为这些问题对于许多抽象来说都是共同的。但是只要看看这个线程上有多少答案,以及直观的解决方案如何在边缘情况下失败。我们已经在 jQuery 中看到了这种模式,当浏览器采用解决我们大多数用例的通用标准时,根本问题就得到了解决。然后性能瓶颈转移到浏览器引擎。我认为 lodash 也应该如此。:) (2认同)

Mar*_*ago 24

最简单的方法是使用 toFixed,然后使用 Number 函数去除尾随零:

const number = 15.5;
Number(number.toFixed(2)); // 15.5
Run Code Online (Sandbox Code Playgroud)
const number = 1.7777777;
Number(number.toFixed(2)); // 1.78
Run Code Online (Sandbox Code Playgroud)

  • 这并不适用于所有情况。在发布答案之前进行广泛的测试。 (3认同)
  • @KevinJhangiani const number = 15; Number(number.toFixed(2)); // 15 - 我在最新的 Chrome 和 Firefox 上测试了它 (2认同)

ast*_*ije 22

MarkG和Lavamantis提供了一个比被接受的解决方案更好的解决方案.遗憾的是他们没有得到更多的赞成!

这是我用来解决基于MDN的浮点小数问题的函数.它比Lavamantis的解决方案更通用(但更简洁):

function round(value, exp) {
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp  = +exp;

  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

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

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}
Run Code Online (Sandbox Code Playgroud)

使用它:

round(10.8034, 2);      // Returns 10.8
round(1.275, 2);        // Returns 1.28
round(1.27499, 2);      // Returns 1.27
round(1.2345678e+2, 2); // Returns 123.46
Run Code Online (Sandbox Code Playgroud)

与Lavamantis的解决方案相比,我们可以......

round(1234.5678, -2); // Returns 1200
round("123.45");      // Returns 123
Run Code Online (Sandbox Code Playgroud)

  • 您的解决方案不包括某些情况,而不是MDN的解决方案.虽然它可能更短,但不准确...... (2认同)

Mat*_*ius 20

从ES6开始,有一种"正确的"方式(没有覆盖静态和创建变通方法),通过使用toPrecision来实现这一点

var x = 1.49999999999;
console.log(x.toPrecision(4));
console.log(x.toPrecision(3));
console.log(x.toPrecision(2));

var y = Math.PI;
console.log(y.toPrecision(6));
console.log(y.toPrecision(5));
console.log(y.toPrecision(4));

var z = 222.987654
console.log(z.toPrecision(6));
console.log(z.toPrecision(5));
console.log(z.toPrecision(4));
Run Code Online (Sandbox Code Playgroud)

  • `(1.005).toPrecision(3)` 实际上仍然返回 `1.00` 而不是 `1.01`。 (3认同)

tot*_*ten 16

这可能对您有所帮助:

var result = (Math.round(input*100)/100);
Run Code Online (Sandbox Code Playgroud)

有关更多信息,您可以查看此链接

Math.round(num)vs num.toFixed(0)和浏览器不一致

  • 为什么被接受的答案比这个答案有更多的票数,因为它们实际上是同一件事,但这个答案是在被接受的答案后一分钟发布的? (2认同)
  • Math.round(1.965 * 100) / 100 将是 1.96 。这是不对的。 (2认同)

小智 16

var roundUpto = function(number, upto){
    return Number(number.toFixed(upto));
}
roundUpto(0.1464676, 2);
Run Code Online (Sandbox Code Playgroud)

toFixed(2) 这里2是我们想要对这个数字进行舍入的数字位数.


Vic*_*dlf 16

2022,原生,无库,现代浏览器,清晰可读。

function round(
  value,
  minimumFractionDigits,
  maximumFractionDigits
) {
  const formattedValue = value.toLocaleString('en', {
    useGrouping: false,
    minimumFractionDigits,
    maximumFractionDigits
  })
  return Number(formattedValue)
}

console.log(round(21.891, 2, 3)) // 21.891
console.log(round(1.8, 2)) // 1.8, if you need 1.80, remove the `Number` function. Return directly the `formattedValue`.
console.log(round(21.0001, 0, 1)) // 21
console.log(round(0.875, 3)) // 0.875
Run Code Online (Sandbox Code Playgroud)

  • 运行这个,看看结果和你写的不一样 (3认同)
  • 其要点是什么?toLocaleString() 应该做什么?它适用于数字“1.015”吗?为什么需要 Number() ?应该有一个解释。来自[帮助中心](https://stackoverflow.com/help/promotion):*“...始终解释为什么您提出的解决方案是合适的以及它是如何工作的”*。请通过[编辑(更改)您的答案](https://stackoverflow.com/posts/70879279/edit) 进行回复,而不是在评论中回复(***没有***“编辑:”、“更新:”或类似 - 答案应该看起来像今天写的一样)。 (3认同)

Shr*_*har 15

它可能适合你,

Math.round(num * 100)/100;
Run Code Online (Sandbox Code Playgroud)

知道toFixed和round之间的区别.您可以查看Math.round(num)与num.toFixed(0)和浏览器不一致.


小智 13

这是一个原型方法:

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

var yournum = 10.55555;
yournum = yournum.round(2);
Run Code Online (Sandbox Code Playgroud)


big*_*ato 13

最简单的方法:

+num.toFixed(2)

它将它转换为字符串,然后返回到整数/浮点数.

  • @Edmund 它应该返回 1.01,而不是 1.00 (2认同)

小智 13

使用类似"parseFloat(parseFloat(value).toFixed(2))"的内容

parseFloat(parseFloat("1.7777777").toFixed(2))-->1.78 
parseFloat(parseFloat("10").toFixed(2))-->10 
parseFloat(parseFloat("9.1").toFixed(2))-->9.1
Run Code Online (Sandbox Code Playgroud)


Jav*_*ome 11

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

myNumber.toLocaleString('en', {maximumFractionDigits:2, useGrouping:false})
Run Code Online (Sandbox Code Playgroud)

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


Amr*_*Ali 11

通常,舍入是通过缩放来完成的: round(num / p) * p

使用指数表示法正确处理+ ve数字的舍入.但是,此方法无法正确舍入边缘情况.

function round(num, precision = 2) {
	var scaled = Math.round(num + "e" + precision);
	return Number(scaled + "e" + -precision);
}

// testing some edge cases
console.log( round(1.005, 2) );  // 1.01 correct
console.log( round(2.175, 2) );  // 2.18 correct
console.log( round(5.015, 2) );  // 5.02 correct

console.log( round(-1.005, 2) );  // -1    wrong
console.log( round(-2.175, 2) );  // -2.17 wrong
console.log( round(-5.015, 2) );  // -5.01 wrong
Run Code Online (Sandbox Code Playgroud)

在这里,我也写了一个函数正确地进行算术舍入.你可以自己测试一下.

/**
 * MidpointRounding away from zero ('arithmetic' rounding)
 * Uses a half-epsilon for correction. (This offsets IEEE-754
 * half-to-even rounding that was applied at the edge cases).
 */

function RoundCorrect(num, precision = 2) {
	// half epsilon to correct edge cases.
	var c = 0.5 * Number.EPSILON * num;
//	var p = Math.pow(10, precision); //slow
	var p = 1; while (precision--> 0) p *= 10;
	if (num < 0)
		p *= -1;
	return Math.round((num + c) * p) / p;
}

// testing some edge cases
console.log(RoundCorrect(1.005, 2));  // 1.01 correct
console.log(RoundCorrect(2.175, 2));  // 2.18 correct
console.log(RoundCorrect(5.015, 2));  // 5.02 correct

console.log(RoundCorrect(-1.005, 2));  // -1.01 correct
console.log(RoundCorrect(-2.175, 2));  // -2.18 correct
console.log(RoundCorrect(-5.015, 2));  // -5.02 correct
Run Code Online (Sandbox Code Playgroud)

  • 嘿@AmrAli。这是一个很棒的答案。为数不多的尽可能准确的之一。谢谢!我特别喜欢“解决方案 2”,因为它的速度。我注意到的一件事是,如果删除“isRound”的提前返回检查,速度可以提高约 5-10%。它添加了更多操作,而不仅仅是运行“decimalAdjust”函数。使用 isRound 提早返回实际上需要更长的时间。 (3认同)
  • 这个答案是一个很好的例子,为什么你不应该只检查 stackoverflow 中的第一条评论。上面那两个根本就是错误的。 (3认同)
  • 像这样的帖子显示了 JavaScipt 是多么愚蠢,只是为了对数字进行四舍五入。为什么 Math.round() 不接受第二个参数来表示要舍入的位数,就像任何明智的语言一样? (3认同)
  • 好的,我刚刚为您添加了它,以及基准测试的屏幕截图。 (2认同)
  • 我在 StackOverflow 上查看了许多解决方案,这个是最好的。带有负数 mod 的指数表示法解决方案似乎最适合货币,并且与后端的 Java 轮计算相匹配。 (2认同)

小智 11

我不喜欢Math.roundBrian Ustas 建议的那样使用,而是更喜欢Math.trunc解决以下情况的方法:

const twoDecimalRound = num => Math.round(num * 100) / 100;
const twoDecimalTrunc = num => Math.trunc(num * 100) / 100;
console.info(twoDecimalRound(79.996)); // Not desired output: 80;
console.info(twoDecimalTrunc(79.996)); // Desired output: 79.99;
Run Code Online (Sandbox Code Playgroud)


Dan*_*eón 10

要不处理多个0,请使用以下变体:

Math.round(num * 1e2) / 1e2
Run Code Online (Sandbox Code Playgroud)


Sco*_*ord 9

如果你碰巧已经在使用d3库,他们有一个强大的数字格式库:https://github.com/mbostock/d3/wiki/Formatting

具体舍入在这里:https://github.com/mbostock/d3/wiki/Formatting#d3_round

在您的情况下,答案是:

> d3.round(1.777777, 2)
1.78
> d3.round(1.7, 2)
1.7
> d3.round(1, 2)
1
Run Code Online (Sandbox Code Playgroud)

  • 看[来源](https://github.com/mbostock/d3/blob/master/src/format/round.js),这只不过是@ustasb答案的通用版本,使用`num*Math .pow(n)`而不是`num*100`(但它绝对是一个整齐的单线;-) (2认同)

Sol*_*tos 8

这是最简单,更优雅的解决方案(我是世界上最好的解决方案;):

function roundToX(num, X) {    
    return +(Math.round(num + "e+"+X)  + "e-"+X);
}
//roundToX(66.66666666,2) => 66.67
//roundToX(10,2) => 10
//roundToX(10.904,2) => 10.9
Run Code Online (Sandbox Code Playgroud)

  • 这是一种很好的方法来重写接受使用`E`表示法接受参数的答案. (4认同)
  • 恕我直言,你的PHP结果是错误的.无论第三个小数后面是什么,如果第三个小数小于5,那么第二个小数应该保持不变.这是数学定义. (4认同)
  • 这在某些边缘情况下不起作用:尝试 ([jsfiddle](https://jsfiddle.net/x5odkv4o/)) `roundToX(362.42499999999995, 2)`。预期结果(如 PHP `echo round(362.42499999999995, 2)` 中所示):`362.43`。实际结果:`362.42` (3认同)
  • 更简洁地说,“e+”可以直接用“e”代替。 (2认同)

Ada*_* A. 8

更简单的ES6方式是

const round = (x, n) => 
  parseFloat(Math.round(x * Math.pow(10, n)) / Math.pow(10, n)).toFixed(n);
Run Code Online (Sandbox Code Playgroud)

此模式还返回所要求的精度.

例如:

round(44.7826456, 4)  // yields 44.7826
round(78.12, 4)       // yields 78.1200
Run Code Online (Sandbox Code Playgroud)


Jin*_*oss 8

如果你想要整理,简单的解决方案就是使用lodash的ceil功能......

https://lodash.com/docs/4.17.10#ceil

_.round(6.001,2)
Run Code Online (Sandbox Code Playgroud)

给出6

_.ceil(6.001, 2);
Run Code Online (Sandbox Code Playgroud)

给出6.01

_.ceil(37.4929,2);
Run Code Online (Sandbox Code Playgroud)

给出37.5

_.round(37.4929,2);
Run Code Online (Sandbox Code Playgroud)

给出37.49

  • 导入新的依赖关系是没有意义的,只是为了进行舍入. (2认同)

小智 8

另一种方法是使用库。为什么不呢lodash

const _ = require("lodash")
const roundedNumber = _.round(originalNumber, 2)
Run Code Online (Sandbox Code Playgroud)


dan*_*y74 8

一个简单的通用解决方案

const round = (n, dp) => {
  const h = +('1'.padEnd(dp + 1, '0')) // 10 or 100 or 1000 or etc
  return Math.round(n * h) / h
}

console.log('round(2.3454, 3)', round(2.3454, 3)) // 2.345
console.log('round(2.3456, 3)', round(2.3456, 3)) // 2.346
console.log('round(2.3456, 2)', round(2.3456, 2)) // 2.35
Run Code Online (Sandbox Code Playgroud)

或者只使用具有相同签名的Lodash round - 例如 _.round(2.3456, 2)


Fel*_*ger 7

基于选择的答案和对同一问题的upvoted评论:

Math.round((num + 0.00001) * 100) / 100
Run Code Online (Sandbox Code Playgroud)

这适用于以下两个示例:

Math.round((1.005 + 0.00001) * 100) / 100

Math.round((1.0049 + 0.00001) * 100) / 100
Run Code Online (Sandbox Code Playgroud)

  • 该功能针对1.004999失败 (2认同)

Wii*_*imm 7

parseFloat(“ 1.555”)。toFixed(2); //返回1.55,而不是1.56。

1.55是绝对正确的结果,因为计算机中不存在1.555的确切表示。如果读数为1.555,则四舍五入为最接近的可能值= 1.55499999999999994(64位浮点型)。并将此数字四舍五入到toFixed(2)将得出1.55。

如果输入为1.55499999999999,则此处提供的所有其他功能都会给出故障结果。

解决方案:在扫描之前将数字“ 5”附加到四舍五入(更精确地说:从0舍入)。仅当数字确实是浮点数(有小数点)时才这样做。

parseFloat("1.555"+"5").toFixed(2); // Returns 1.56
Run Code Online (Sandbox Code Playgroud)


KFi*_*ish 7

在经过所有可能的方式的各种迭代以达到真正准确的十进制舍入精度之后,很明显,最准确和有效的解决方案是使用Number.EPSILON。这为浮点数学精度问题提供了一个真正的数学解决方案。可以很容易地对其进行填充,如下所示:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON以支持所有剩余的IE用户(那么也许我们再次应该停止这样做)。

改编自此处提供的解决方案:https : //stackoverflow.com/a/48850944/6910392

一种简单的解决方案,可提供准确的小数舍入,下限和上限,并带有可选的precision变量,而无需添加整个库。

var DecimalPrecision = (function(){
        if (Number.EPSILON === undefined) {
            Number.EPSILON = Math.pow(2, -52);
        }
        this.round = function(n, p=2){
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            if(n < 0)
                o *= -1;
            return Math.round((n + r) * o) / o;
        }
        this.ceil = function(n, p=2){
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            if(n < 0)
                o *= -1;
            return Math.ceil((n + r) * o) / o;
        }
        this.floor = function(n, p=2){
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            if(n < 0)
                o *= -1;
            return Math.floor((n + r) * o) / o;
        }
        return this;
    })();
    console.log(DecimalPrecision.round(1.005));
    console.log(DecimalPrecision.ceil(1.005));
    console.log(DecimalPrecision.floor(1.005));
    console.log(DecimalPrecision.round(1.0049999));
    console.log(DecimalPrecision.ceil(1.0049999));
    console.log(DecimalPrecision.floor(1.0049999));
    console.log(DecimalPrecision.round(2.175495134384,7));
    console.log(DecimalPrecision.round(2.1753543549,8));
    console.log(DecimalPrecision.round(2.1755465135353,4));
Run Code Online (Sandbox Code Playgroud)


Mar*_*ima 6

我将再添加一个方法.

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"
Run Code Online (Sandbox Code Playgroud)

.toFixed(2)返回一个带有2个小数点的字符串,可能是也可能不是尾随零.做一个parseFloat()将消除那些尾随零.


pro*_*ica 6

将类型保留为整数,以便以后进行排序或其他数学运算:

Math.round(1.7777777 * 100)/100
Run Code Online (Sandbox Code Playgroud)

1.78

// Round up!
Math.ceil(1.7777777 * 100)/100 
Run Code Online (Sandbox Code Playgroud)

1.78

// Round down!
Math.floor(1.7777777 * 100)/100
Run Code Online (Sandbox Code Playgroud)

1.77

或转换为字符串:

(1.7777777).toFixed(2)
Run Code Online (Sandbox Code Playgroud)

“ 1.77”

  • OP显然希望“ 1.7777777”成为“ 1.78”,而不是“ 1.77” (2认同)

Sal*_*man 6

问题是四舍五入到小数点后两位。

\n

让\xe2\x80\x99s不要让这个变得复杂,修改原型链等等。

\n

这是单行解决方案

\n

\r\n
\r\n
let round2dec = num => Math.round(num * 100) / 100;\n\nconsole.log(round2dec(1.77));\nconsole.log(round2dec(1.774));\nconsole.log(round2dec(1.777));\nconsole.log(round2dec(10));
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n


Kam*_*ski 6

数学下限和回合定义

在此输入图像描述

带领我们到

let round= x=> ( x+0.005 - (x+0.005)%0.01 +'' ).replace(/(\...)(.*)/,'$1');

// for a case like 1.384 we need to use a regexp to get only 2 digits after the dot
// and cut off machine-error (epsilon)

console.log(round(10));
console.log(round(1.7777777));
console.log(round(1.7747777));
console.log(round(1.384));
Run Code Online (Sandbox Code Playgroud)


Ale*_*IOT 6

我查看了这篇文章的每个答案。以下是我对此事的看法:

const nbRounds = 7;
const round = (x, n=2) => {
  const precision = Math.pow(10, n)
  return Math.round((x+Number.EPSILON) * precision ) / precision;
}
let i = 0;
while( nbRounds > i++ ) {
  console.log("round(1.00083899, ",i,") > ", round(1.00083899, i))
  console.log("round(1.83999305, ",i,") > ", round(1.83999305, i))
}
Run Code Online (Sandbox Code Playgroud)


小智 6

我读过所有的答案,类似问题的答案和最“好”解决方案的复杂性并不能令我满意。我不想放置一个巨大的圆形函数集,或者一个小但在科学记数法上失败的函数集。所以,我想出了这个功能。它可能会帮助处于我这种情况的人:

function round(num, dec) {
   const [sv, ev] = num.toString().split('e');
   return Number(Number(Math.round(parseFloat(sv + 'e' + dec)) + 'e-' + dec) + 'e' + (ev || 0));
}
Run Code Online (Sandbox Code Playgroud)

我没有运行任何性能测试,因为我调用它只是为了更新应用程序的 UI。该函数给出以下快速测试结果:

// 1/3563143 = 2.806510993243886e-7
round(1/3563143, 2)  // returns `2.81e-7`

round(1.31645, 4)    // returns 1.3165

round(-17.3954, 2)   // returns -17.4
Run Code Online (Sandbox Code Playgroud)

这对我来说就足够了。


lor*_*isi 5

要按小数点四舍五入pos(包括没有小数),请执行以下操作Math.round(num * Math.pow(10,pos)) / Math.pow(10,pos)

var console = {
 log: function(s) {
  document.getElementById("console").innerHTML += s + "<br/>"
 }
}
var roundDecimals=function(num,pos) {
 return (Math.round(num * Math.pow(10,pos)) / Math.pow(10,pos) );
}
//https://en.wikipedia.org/wiki/Pi
var pi=3.14159265358979323846264338327950288419716939937510;
for(var i=2;i<15;i++) console.log("pi="+roundDecimals(pi,i));
for(var i=15;i>=0;--i) console.log("pi="+roundDecimals(pi,i));
Run Code Online (Sandbox Code Playgroud)
<div id="console" />
Run Code Online (Sandbox Code Playgroud)


Nic*_*olo 5

我知道有很多答案,但大多数答案在某些特定情况下都有副作用.

最简单,最短的解决方案没有任何副作用如下:

Number((2.3456789).toFixed(2)) // 2.35
Run Code Online (Sandbox Code Playgroud)

它正确地舍入并返回数字而不是字符串

console.log(Number((2.345).toFixed(2)))  // 2.35
console.log(Number((2.344).toFixed(2)))  // 2.34
console.log(Number((2).toFixed(2)))      // 2
console.log(Number((-2).toFixed(2)))     // -2
console.log(Number((-2.345).toFixed(2))) // -2.35

console.log(Number((2.345678).toFixed(3))) // 2.346
Run Code Online (Sandbox Code Playgroud)

  • console.log(Number((1.005).toFixed(2)))仍然给出"1.00"而不是"1.01" (4认同)

Ros*_*oss 5

这对我来说是个窍门(TypeScript):

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;
}

// Sample output:
Rounded 18.339840000000436 to 18.34
Rounded 52.48283999999984 to 52.48
Rounded 57.24612000000036 to 57.25
Rounded 23.068320000000142 to 23.07
Rounded 7.792980000000398 to 7.79
Rounded 31.54157999999981 to 31.54
Rounded 36.79686000000004 to 36.8
Rounded 34.723080000000124 to 34.72
Rounded 8.4375 to 8.44
Rounded 15.666960000000074 to 15.67
Rounded 29.531279999999924 to 29.53
Rounded 8.277420000000006 to 8.28
Run Code Online (Sandbox Code Playgroud)


小智 5

这个功能对我有用。您只需传入数字和要舍入的位置,它就可以轻松完成所需的工作。

round(source, n) {
  let places = Math.pow(10, n);

  return Math.round(source * places) / places;
}
Run Code Online (Sandbox Code Playgroud)


Moh*_*fei 5

一个简单的通用舍入函数可能如下:

步骤是:

  1. 使用Math.pow(10,places)将数字乘以(10 的小数位数的幂
  2. 使用Math.Round将结果四舍五入为整数。
  3. 将结果除以(10 的小数位数的幂)Math.pow(10,places)

例子:

数字是: 1.2375 四舍五入到小数点后 3 位

  1. 1.2375 * (10^3)​​ ==> 1.2375 * 1000 = 1237.5
  2. 舍入为整数 ==> 1238
  3. 1238 除以 (10^3)​​ ==> 1238 / 1000 = 1.238

(注意:10^3 表示 Math.pow(10,3))。

 function numberRoundDecimal(v,n) {
 return Math.round((v+Number.EPSILON)*Math.pow(10,n))/Math.pow(10,n)}


// ------- tests --------
console.log(numberRoundDecimal(-0.024641163062896567,3))  // -0.025
console.log(numberRoundDecimal(0.9993360575508052,3))     // 0.999
console.log(numberRoundDecimal(1.0020739645577939,3))     // 1.002
console.log(numberRoundDecimal(0.975,0))                  // 1
console.log(numberRoundDecimal(0.975,1))                  // 1
console.log(numberRoundDecimal(0.975,2))                  // 0.98
console.log(numberRoundDecimal(1.005,2))                  // 1.01
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

2198849 次

最近记录:

5 年,10 月 前