这一行代码把数字四舍五入到小数点后两位。但我得到的数字是这样的:10.8、2.4等等。这些都不是我的小数点后两位的想法,所以我怎么能改善以下?

Math.round(price*Math.pow(10,2))/Math.pow(10,2);

我想要10.80、2.40等数字。jQuery的使用对我来说很好。


当前回答

下面是https://stackoverflow.com/a/21323330/916734的TypeScript实现。它还使用了函数,并允许可选的数字偏移量。

export function round(rawValue: number | string, precision = 0, fractionDigitOffset = 0): number | string {
  const value = Number(rawValue);
  if (isNaN(value)) return rawValue;

  precision = Number(precision);
  if (precision % 1 !== 0) return NaN;

  let [ stringValue, exponent ] = scientificNotationToParts(value);

  let shiftExponent = exponentForPrecision(exponent, precision, Shift.Right);
  const enlargedValue = toScientificNotation(stringValue, shiftExponent);
  const roundedValue = Math.round(enlargedValue);

  [ stringValue, exponent ] = scientificNotationToParts(roundedValue);
  const precisionWithOffset = precision + fractionDigitOffset;
  shiftExponent = exponentForPrecision(exponent, precisionWithOffset, Shift.Left);

  return toScientificNotation(stringValue, shiftExponent);
}

enum Shift {
  Left = -1,
  Right = 1,
}

function scientificNotationToParts(value: number): Array<string> {
  const [ stringValue, exponent ] = value.toString().split('e');
  return [ stringValue, exponent ];
}

function exponentForPrecision(exponent: string, precision: number, shift: Shift): number {
  precision = shift * precision;
  return exponent ? (Number(exponent) + precision) : precision;
}

function toScientificNotation(value: string, exponent: number): number {
  return Number(`${value}e${exponent}`);
}

其他回答

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

天真的实现

使用下面带有中间数的函数,您将得到预期的上四舍五入值,或者有时根据输入得到下四舍五入值。

这种舍入不一致可能会在客户端代码中引入难以检测的错误。

函数naiveRound(num, decimalPlaces) { var p =数学。decimalPlaces战俘(10日); 返回数学。Round (num * p) / p; } console.log(naiveRound(1.245, 2));// 1.25 correct(四舍五入) console.log(naiveRound(1.255, 2));// 1.25不正确(应该是1.26)

更好的实现

通过将数字转换为指数表示法中的字符串,正数将按预期四舍五入。 但是要注意,负数四舍五入和正数四舍五入是不同的。

事实上,它的执行基本上相当于“四舍五入”的规则,您将看到round(-1.005, 2)的计算结果为-1,即使round(1.005, 2)的计算结果为1.01。lodash _。圆法使用这种技术。

/** * Round half up ('round half towards positive infinity') * Uses exponential notation to avoid floating-point issues. * Negative numbers round differently than positive numbers. */ function round(num, decimalPlaces) { num = Math.round(num + "e" + decimalPlaces); return Number(num + "e" + -decimalPlaces); } // test rounding of half console.log( round(0.5, 0) ); // 1 console.log( round(-0.5, 0) ); // 0 // testing edge cases console.log( round(1.005, 2) ); // 1.01 console.log( round(2.175, 2) ); // 2.18 console.log( round(5.015, 2) ); // 5.02 console.log( round(-1.005, 2) ); // -1 console.log( round(-2.175, 2) ); // -2.17 console.log( round(-5.015, 2) ); // -5.01

如果希望在负数舍入时保持通常的行为,则需要在调用Math.round()之前将负数转换为正数,然后在返回之前将它们转换回负数。

// Round half away from zero
function round(num, decimalPlaces) {
    num = Math.round(Math.abs(num) + "e" + decimalPlaces) * Math.sign(num);
    return Number(num + "e" + -decimalPlaces);
}

有一种不同的纯数学技术来执行舍入到最近(使用“舍入到离零一半远的地方”),在调用舍入函数之前应用epsilon校正。

简单地说,我们添加最小的浮动值(= 1.0 ulp;单位在最后的位置)到数字之前舍入。这将移动到数字之后的下一个可表示的值,远离零。

/** * Round half away from zero ('commercial' rounding) * Uses correction to offset floating-point inaccuracies. * Works symmetrically for positive and negative numbers. */ function round(num, decimalPlaces) { var p = Math.pow(10, decimalPlaces); var e = Number.EPSILON * num * p; return Math.round((num * p) + e) / p; } // test rounding of half console.log( round(0.5, 0) ); // 1 console.log( round(-0.5, 0) ); // -1 // testing edge cases console.log( round(1.005, 2) ); // 1.01 console.log( round(2.175, 2) ); // 2.18 console.log( round(5.015, 2) ); // 5.02 console.log( round(-1.005, 2) ); // -1.01 console.log( round(-2.175, 2) ); // -2.18 console.log( round(-5.015, 2) ); // -5.02

这是为了抵消十进制数编码过程中可能出现的隐式舍入误差,特别是十进制数的最后一个位置有“5”的数字,如1.005、2.675和16.235。实际上,十进制系统中的1.005在64位二进制浮点数中被编码为1.0049999999999999;而十进制系统中的1234567.005被编码为64位二进制浮点的1234567.0049999998882413。

值得注意的是,二进制舍入误差的最大值取决于(1)数字的大小和(2)相对机器的ε(2^-52)。

将以下内容放在全局范围内:

Number.prototype.getDecimals = function ( decDigCount ) {
   return this.toFixed(decDigCount);
}

然后试试:

var a = 56.23232323;
a.getDecimals(2); // will return 56.23

更新

请注意,toFixed()只能适用于0-20之间的小数,即a.g getdecimals(25)可能会生成一个javascript错误,所以为了适应,你可以添加一些额外的检查,即。

Number.prototype.getDecimals = function ( decDigCount ) {
   return ( decDigCount > 20 ) ? this : this.toFixed(decDigCount);
}

@heridev和我用jQuery创建了一个小函数。

接下来你可以试试:

HTML

<input type="text" name="one" class="two-digits"><br>
<input type="text" name="two" class="two-digits">​

jQuery

// apply the two-digits behaviour to elements with 'two-digits' as their class
$( function() {
    $('.two-digits').keyup(function(){
        if($(this).val().indexOf('.')!=-1){         
            if($(this).val().split(".")[1].length > 2){                
                if( isNaN( parseFloat( this.value ) ) ) return;
                this.value = parseFloat(this.value).toFixed(2);
            }  
         }            
         return this; //for chaining
    });
});

​ 在线演示:

http://jsfiddle.net/c4Wqn/

我通常把它添加到我的个人库中,在一些建议和使用@TIMINeutron解决方案之后,并使其适用于十进制长度,这一个最适合:

function precise_round(num, decimals) {
   var t = Math.pow(10, decimals);   
   return (Math.round((num * t) + (decimals>0?1:0)*(Math.sign(num) * (10 / Math.pow(100, decimals)))) / t).toFixed(decimals);
}

将工作的例外报告。

我不知道为什么我不能在之前的答案上添加评论(也许我是绝望的盲人,我不知道),但我用@Miguel的答案想出了一个解决方案:

function precise_round(num,decimals) {
   return Math.round(num*Math.pow(10, decimals)) / Math.pow(10, decimals);
}

它的两条评论(来自@bighostkim和@Imre):

precise_round(1.275,2)不返回1.28的问题 precise_round(6,2)不返回6.00(正如他想要的)的问题。

我最终的解决方案如下:

function precise_round(num,decimals) {
    var sign = num >= 0 ? 1 : -1;
    return (Math.round((num*Math.pow(10,decimals)) + (sign*0.001)) / Math.pow(10,decimals)).toFixed(decimals);
}

正如你所看到的,我必须添加一点“更正”(这不是它是什么,但因为数学。round是有损的-你可以在jsfiddle.net上检查它-这是我知道如何“修复”它的唯一方法)。它在已经填充的数字上加了0.001,所以它在十进制值的右边加了一个1 3个0。所以使用起来应该是安全的。

之后,我添加了. tofixed(十进制),以始终以正确的格式输出数字(具有正确数量的小数)。

差不多就是这样了。好好使用它;)

编辑:增加了负数“更正”功能。