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

Smu*_*ger 389 javascript math

我有以下JavaScript语法:

var discount = Math.round(100 - (price / listprice) * 100);
Run Code Online (Sandbox Code Playgroud)

这可以达到整数.如何以小数点后两位返回结果?

Ric*_*der 735

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

var discount = (price / listprice).toFixed(2);
Run Code Online (Sandbox Code Playgroud)

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

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

虽然需要一个小的修改,上面链接的答案中的函数在它舍入为1时返回整数,所以例如99.004将返回99而不是99.00,这不是显示价格的理想选择.

编辑3 - 似乎在实际返回时有toFixed是STILL搞砸了一些数字,这个最终编辑似乎工作.Geez这么多的返工!

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

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

编辑4 - 你们要杀了我.编辑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(2);
    if( negative ) {    
        n = (n * -1).toFixed(2);
    }
    return n;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 将数字转换为字符串,返回数字似乎是一项非常繁重的工作.我发现`Math.round(x*100)/ 100;`是最简单,最简单的方法来舍入到两位小数. (65认同)
  • .toFixed返回一个字符串而不是一个数字但是 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed (23认同)
  • Downvote,因为效率非常低(在我的机器上它需要比Math.round长400倍)http://jsperf.com/round-numbers-to-2-digits (9认同)
  • 对于那些继续使用ES6语法建议编辑的人,请停止它.除非ES6在所有浏览器中本地呈现,否则我的答案都不会以这种方式编写,除非问题是专门要求它.不是每个人都在使用转换器. (7认同)
  • 确保你使用toFixed的项目是一个数字,你可以先解析它. (4认同)
  • 足够认真地讲,这样做的目的是要回答最初的问题,这个答案就是这样做的。如果您一定有一个更好的答案,请添加它,但是仔细挑选一个6年的答案,因为它不能四舍五入到小数点后两位,这确实是该网站的问题。 (3认同)
  • @RickCalder错过了评论,对不起.但是,当答案不完全正确或至少没有说明其缺点时,谷歌搜索"js舍入浮动到小数位"时,结果中显示相当高的4岁回答,我感到很遗憾.而你的观点"价格,*几乎*永远不会在小数点后3位表示"非常弱,因为在进行某些计算时(例如折扣后),舍入前的价格表示很容易有很多十进制数字. (2认同)
  • `return +(test.toFixed(2));` 应该使用 `digits` 参数。 (2认同)
  • @DavidDunham ......你们非常挑剔一种对于数学来说并不是很好的语言.请参见编辑4 (2认同)
  • 无法与 8200.005 正常工作示例:https://jsfiddle.net/rdLse87k/ (2认同)
  • 这里所有混乱的答案让我觉得我们应该使用一个库来进行数值计算! (2认同)

Joh*_*zen 127

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

例如:+discount.toFixed(2)

  • 真的,你应该使用`parseFloat(discount.toFixed(2))`而不是强制类型coersion,因为它对其他人来说更明显(以后你) (7认同)
  • 你的答案不起作用:`parseFloat((1.005).toFixed(2))` 应该给出 `1.01`,而不是 `1.00` (3认同)
  • 离合器,我现在也将它与 +new Date() 一起使用 (2认同)
  • @neaumusic你可以使用`Date.now()` (2认同)

Arn*_*ekk 45

Math.round()和.toFixed()函数用于舍入到最接近的整数.处理小数并使用Math.round()的"multiply and divide"方法或.toFixed()的参数时,会得到不正确的结果.例如,如果您尝试使用Math.round(1.005*100)/ 100对1.005进行舍入,那么您将使用.toFixed(2)获得1和1.00的结果,而不是获得1.01的正确答案.

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

Number(Math.round(100 - (price / listprice) * 100 + 'e2') + 'e-2');
Run Code Online (Sandbox Code Playgroud)

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

Number(Math.round(100 - (price / listprice) * 100 + 'e2') + 'e-2').toFixed(2);
Run Code Online (Sandbox Code Playgroud)

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

function round(value, decimals) {
    return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
}
Run Code Online (Sandbox Code Playgroud)

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

吴国良

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

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

并像这样使用它:

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

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

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

  • 他们可能会投票,因为这不是一个错误.`Math.round()`意味着舍入到最接近的整数,并且人们通常不赞成并尝试不改变这样的内置方法,以防有人期望该功能就像他们去代码时那样在你身后.但是你的代码是合理的,并且+1用于指出`Math.round()`的限制. (6认同)
  • 这种方法不适用于字符串表示已经有指数的数字。例如,任何`1e+21` 或更高的值都会返回`NaN`。 (4认同)

Cat*_*ode 28

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

var discount = Math.round((100 - (price / listprice) * 100) * 100) / 100;
Run Code Online (Sandbox Code Playgroud)

要舍入的值乘以100以保持前两位数,然后我们除以100以得到实际结果.

  • @DejayClayton它出了什么问题?我甚至认为这是值得投资的. (2认同)
  • @DejayClayton实际上,这是正确的方法,没有经过转换为字符串和返回数字的kludge. (2认同)
  • 对不起,我不知道我实际在抱怨什么,除了它看起来像混杂的无差别魔法数字.但我想这很简洁. (2认同)

Nag*_*tti 16

我找到的最好和最简单的解决方案是

function round(value, decimals) {
 return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
}   
round(1.005, 2); // 1.01
Run Code Online (Sandbox Code Playgroud)

参考:http: //www.jacklmoore.com/notes/rounding-in-javascript/

  • 此解决方案不适用于 JS 已经以字符串形式以科学记数法表示的值。尝试调用 round(0.0000000001, 2) 会得到错误的答案。对于这样一个简单的数学运算,在数字和字符串之间切换*两次*也是完全愚蠢的。 (3认同)
  • 第一个有效的解决方案! (2认同)
  • 该解决方案也不适用于打字稿 (2认同)

Har*_*ish 14

尝试使用 discount.toFixed(2);


小智 13

我认为我看到它的最好方法是将数字乘以10乘以数字,然后再进行Math.round,最后将数字除以10.这是我在打字稿中使用的一个简单函数:

function roundToXDigits(value: number, digits: number) {
    value = value * Math.pow(10, digits);
    value = Math.round(value);
    value = value / Math.pow(10, digits);
    return value;
}
Run Code Online (Sandbox Code Playgroud)

或者简单的javascript:

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

  • @brainbag是的,但只是由于浮点数学。`1.005 * Math.pow(10, 2)` 是 `100.49999999999999` 所以向下舍入。如果不引入 BigNumbers 库或其他东西,你对此无能为力。`roundToXDigits(1.05, 1)` 正确返回,`roundToXDigits(1.0005, 3)` 等也正确返回。 (2认同)

Hal*_*tle 7

接受答案的一个小变化. toFixed(2)返回一个字符串,你总会得到两个小数位.这些可能是零.如果你想压制最终零(s),只需这样做:

var discount = + ((price / listprice).toFixed(2));
Run Code Online (Sandbox Code Playgroud)

编辑:我刚刚发现Firefox 35.0.1中似乎是一个错误,这意味着上面的内容可能会给NaN一些值.
我已将代码更改为

var discount = Math.round(price / listprice * 100) / 100;
Run Code Online (Sandbox Code Playgroud)

这给出了一个最多两位小数的数字.如果你想要三个,你会乘以除以1000,依此类推.
OP总是想要两位小数,但如果在Firefox中使用toFixed(),则需要先修复.
请参阅https://bugzilla.mozilla.org/show_bug.cgi?id=1134388


Kam*_*y D 5

最快的方式 - 比toFixed()更快:

两个十分之一

x      = .123456
result = Math.round(x * 100) / 100  // result .12
Run Code Online (Sandbox Code Playgroud)

三个十分之一

x      = .123456
result = Math.round(x * 1000) / 1000      // result .123
Run Code Online (Sandbox Code Playgroud)

  • 快但错:`Math.round(1.005*100)/ 100`返回`1` (5认同)