Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/405.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如有必要,如何舍入到最多两位小数?_Javascript_Rounding_Decimal Point - Fatal编程技术网

Javascript 如有必要,如何舍入到最多两位小数?

Javascript 如有必要,如何舍入到最多两位小数?,javascript,rounding,decimal-point,Javascript,Rounding,Decimal Point,我想最多四舍五入两位小数,但只有在必要的时候 输入: 10 1.7777777 9.1 输出: 10 1.78 9.1 如何在JavaScript中实现这一点 使用: 或者更具体地说,为了确保像1.005轮这样的东西正确,请使用: 这可能会帮助您: var result = Math.round(input*100)/100; 有关更多信息,请查看此链接 考虑.toFixed()和.toPrecision(): 它可能适合你 Math.round(num * 100)/100; 要知道t

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

输入:

10
1.7777777
9.1
输出:

10
1.78
9.1
如何在JavaScript中实现这一点

使用:

或者更具体地说,为了确保像1.005轮这样的东西正确,请使用:

这可能会帮助您:

var result = Math.round(input*100)/100;
有关更多信息,请查看此链接

考虑
.toFixed()
.toPrecision()

它可能适合你

Math.round(num * 100)/100;

要知道toFixed和round的区别。您可以看看。

这里有一个简单的方法:

Math.round(value * 100) / 100
不过,您可能希望继续并创建一个单独的函数来为您执行此操作:

function roundToTwo(value) {
    return(Math.round(value * 100) / 100);
}
然后您只需传入值

通过添加第二个参数,可以将其增强为任意小数位数

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

    return (Math.round(value * multiplier) / multiplier);
}

如果该值为文本类型:

parseFloat("123.456").toFixed(2);
如果该值是一个数字:

var numb = 123.23454;
numb = numb.toFixed(2);
有一个缺点是,像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.
看起来像是数学。圆形是一个更好的解决方案但事实并非如此在某些情况下,它将正确舍入:

Math.round(1.005 * 1000)/1000 // Returns 1 instead of expected 1.01!
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.
// 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
我猜,这是因为1.555实际上在幕后类似于float 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);
  }
}

注意:这不是一个适用于所有人的通用解决方案。有几种不同的舍入算法,您的实现可能会有所不同,这取决于您的需求

解决方案2旨在避免前端计算,并从后端服务器获取舍入值

编辑:另一种可能的解决方案,也不是防弹的

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

在某些情况下,当您将数字(如1.354999999998)四舍五入时,它将返回不正确的结果。应该是1.35,但结果是1.36。

这里没有一个答案是正确的@臭车夫要求你把数字四舍五入

要汇总,请使用以下命令:

Math.ceil(num * 100)/100;

以下是一个原型方法:

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

var yournum = 10.55555;
yournum = yournum.round(2);
你可以用

function roundToTwo(num) {    
    return +(Math.round(num + "e+2")  + "e-2");
}
我发现这是我的车。他们的方法避免了1.005的问题


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

Math.round(num * 1e2) / 1e2

马克的答案是正确的。这里是任意小数位数的通用扩展

Number.prototype.round = function(places) {
  return +(Math.round(this + "e+" + places)  + "e-" + places);
}
用法:

var n = 1.7777;    
n.round(2); // 1.78
单元测试:

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

MarkG和Lavamantis提供了一个比已被接受的解决方案好得多的解决方案。可惜他们没有得到更多的选票

下面是我用来解决浮点小数问题的函数。它甚至比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));
}
function round(x, digits){
  return parseFloat(x.toFixed(digits))
}

 round(1.222,  2) ;
 // 1.22
 round(1.222, 10) ;
 // 1.222
将其用于:

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
与拉瓦曼蒂斯的解决方案相比,我们可以做到

round(1234.5678, -2); // Returns 1200
round("123.45");      // Returns 123

精确的四舍五入方法。资料来源:

示例:

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.
// 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

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

尝试此轻质解决方案:

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));
}
function round(x, digits){
  return parseFloat(x.toFixed(digits))
}

 round(1.222,  2) ;
 // 1.22
 round(1.222, 10) ;
 // 1.222
可以使用
.toFixed(小数位数)

最简单的方法:

+num.toFixed(2)

它将其转换为字符串,然后再转换回整数/浮点

var roundUpto = function(number, upto){
    return Number(number.toFixed(upto));
}
roundUpto(0.1464676, 2);

toFixed(2)
这里2是我们要将该数字四舍五入的位数。

只有在必要时才能实现这种四舍五入的一种方法是使用:


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

有几种方法可以做到这一点。对于像我这样的人来说,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))
}
用法:

round(0.015, 2) // 0.02
round(1.005, 2) // 1.01
如果您的项目使用jQuery或lodash,您还可以在库中找到合适的
round
方法

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

这个问题很复杂

假设我们有一个函数,
roundTo2DP(num)
,它将浮点值作为参数,并返回一个四舍五入到小数点后2位的值。这些表达式的计算结果应该是什么

  • roundTo2DP(0.014999999999999)
  • roundTo2DP(0.0150000000000000001)
  • roundTo2DP(0.015)
“显而易见”的答案是,第一个例子应该四舍五入到0.01(因为它更接近于0.01而不是0.02),而另外两个例子应该四舍五入到0.02(因为0.0150000000001更接近于0.02而不是0.01,因为0.015正好介于两者之间,并且有一个数学约定,这些数字会被四舍五入)

您可能已经猜到了一个问题,即不可能实现
roundTo2DP
来给出这些明显的答案,因为传递给它的所有三个数字都是相同的数字。IEEE 754二进制浮点数(JavaScript使用的那种)不能准确地表示大多数非整数,因此上面的三个数字文本都会四舍五入到附近的有效浮点数。这个数字恰好是

0.01499999999994448884876874217297818416595458984375

这比0.02更接近于0.01

您可以在浏览器控制台、节点shell或其他JavaScript解释器中看到这三个数字都是相同的。比较一下:

> 0.014999999999999999 === 0.0150000000000000001
true
。。。我得到了0.015,应该四舍五入到0.02,这显然不是我之前说的所有这些数字都完全等于的56位小数。那么这是什么黑魔法呢

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

设n,k,s为整数,使得k≥ 110K-1≤ s<10k,s×10n的数值-
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))
}
round(0.015, 2) // 0.02
round(1.005, 2) // 1.01
> 0.014999999999999999 === 0.0150000000000000001
true
> var m = 0.0150000000000000001;
> console.log(String(m));
0.015
> var m = 0.014999999999999999;
> console.log(String(m));
0.015
/**
 * 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+$/, '')
}
> 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'
/**
 * 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);
}
Math.round( num * 100 + Number.EPSILON ) / 100
Math.round( ( num + Number.EPSILON ) * 100 ) / 100
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 ;
}
_.round(number, precision)
_.round(1.7777777, 2) = 1.78
number = 1.2345;
number.toFixed(2) // "1.23"
number = 1; // "1"
number.toFixed(5).replace(/\.?0*$/g,'');
const number = 15.5;
Number(number.toFixed(2)); // 15.5
const number = 1.7777777;
Number(number.toFixed(2)); // 1.78