这一行代码把数字四舍五入到小数点后两位。但我得到的数字是这样的:10.8、2.4等等。这些都不是我的小数点后两位的想法,所以我怎么能改善以下?
Math.round(price*Math.pow(10,2))/Math.pow(10,2);
我想要10.80、2.40等数字。jQuery的使用对我来说很好。
这一行代码把数字四舍五入到小数点后两位。但我得到的数字是这样的:10.8、2.4等等。这些都不是我的小数点后两位的想法,所以我怎么能改善以下?
Math.round(price*Math.pow(10,2))/Math.pow(10,2);
我想要10.80、2.40等数字。jQuery的使用对我来说很好。
当前回答
这是我的1行解决方案:Number((yourNumericValueHere).toFixed(2));
事情是这样的:
1)首先,你将. tofixed(2)应用到你想要四舍五入的小数上。注意,这将把值从number转换为字符串。所以如果你使用Typescript,它会抛出一个这样的错误:
" string类型不能赋值给number类型"
2)要返回数值或将字符串转换为数值,只需对所谓的“字符串”值应用Number()函数。
为了说明问题,请看下面的例子:
例子: 我有一个金额,有高达5位小数,我想缩短到2位小数。我是这样做的:
Var价格= 0.26453; var priceround = Number((价格).toFixed(2)); console.log('原始价格:' +价格); console.log('价格四舍五入:' + pricerounds);
其他回答
我没有找到这个问题的准确解决方案,所以我自己创造了一个:
function inprecise_round(value, decPlaces) {
return Math.round(value*Math.pow(10,decPlaces))/Math.pow(10,decPlaces);
}
function precise_round(value, decPlaces){
var val = value * Math.pow(10, decPlaces);
var fraction = (Math.round((val-parseInt(val))*10)/10);
//this line is for consistency with .NET Decimal.Round behavior
// -342.055 => -342.06
if(fraction == -0.5) fraction = -0.6;
val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
return val;
}
例子:
function inprecise_round(value, decPlaces) { return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces); } function precise_round(value, decPlaces) { var val = value * Math.pow(10, decPlaces); var fraction = (Math.round((val - parseInt(val)) * 10) / 10); //this line is for consistency with .NET Decimal.Round behavior // -342.055 => -342.06 if (fraction == -0.5) fraction = -0.6; val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces); return val; } // This may produce different results depending on the browser environment console.log("342.055.toFixed(2) :", 342.055.toFixed(2)); // 342.06 on Chrome & IE10 console.log("inprecise_round(342.055, 2):", inprecise_round(342.055, 2)); // 342.05 console.log("precise_round(342.055, 2) :", precise_round(342.055, 2)); // 342.06 console.log("precise_round(-342.055, 2) :", precise_round(-342.055, 2)); // -342.06 console.log("inprecise_round(0.565, 2) :", inprecise_round(0.565, 2)); // 0.56 console.log("precise_round(0.565, 2) :", precise_round(0.565, 2)); // 0.57
浮点值的问题在于,它们试图用固定数量的比特表示无限数量的(连续的)值。所以自然地,在游戏中一定会有一些损失,你会被一些价值观咬伤。
当计算机将1.275存储为浮点值时,它实际上不会记住它是1.275还是1.27499999999999993,甚至是1.27500000000000002。这些值在四舍五入到两个小数后应该会给出不同的结果,但它们不会,因为对于计算机来说,它们存储为浮点值后看起来完全相同,并且没有办法恢复丢失的数据。任何进一步的计算只会积累这样的不精确性。
因此,如果精度很重要,就必须从一开始就避免使用浮点值。最简单的选择是
使用专门的图书馆 使用字符串存储和传递值(附带字符串操作) 使用整数(例如,你可以传递实际值的百分之一,例如,用美分代替美元)
例如,当使用整数存储百分位数时,查找实际值的函数非常简单:
function descale(num, decimals) {
var hasMinus = num < 0;
var numString = Math.abs(num).toString();
var precedingZeroes = '';
for (var i = numString.length; i <= decimals; i++) {
precedingZeroes += '0';
}
numString = precedingZeroes + numString;
return (hasMinus ? '-' : '')
+ numString.substr(0, numString.length-decimals)
+ '.'
+ numString.substr(numString.length-decimals);
}
alert(descale(127, 2));
对于字符串,你需要四舍五入,但它仍然是可控的:
function precise_round(num, decimals) {
var parts = num.split('.');
var hasMinus = parts.length > 0 && parts[0].length > 0 && parts[0].charAt(0) == '-';
var integralPart = parts.length == 0 ? '0' : (hasMinus ? parts[0].substr(1) : parts[0]);
var decimalPart = parts.length > 1 ? parts[1] : '';
if (decimalPart.length > decimals) {
var roundOffNumber = decimalPart.charAt(decimals);
decimalPart = decimalPart.substr(0, decimals);
if ('56789'.indexOf(roundOffNumber) > -1) {
var numbers = integralPart + decimalPart;
var i = numbers.length;
var trailingZeroes = '';
var justOneAndTrailingZeroes = true;
do {
i--;
var roundedNumber = '1234567890'.charAt(parseInt(numbers.charAt(i)));
if (roundedNumber === '0') {
trailingZeroes += '0';
} else {
numbers = numbers.substr(0, i) + roundedNumber + trailingZeroes;
justOneAndTrailingZeroes = false;
break;
}
} while (i > 0);
if (justOneAndTrailingZeroes) {
numbers = '1' + trailingZeroes;
}
integralPart = numbers.substr(0, numbers.length - decimals);
decimalPart = numbers.substr(numbers.length - decimals);
}
} else {
for (var i = decimalPart.length; i < decimals; i++) {
decimalPart += '0';
}
}
return (hasMinus ? '-' : '') + integralPart + (decimals > 0 ? '.' + decimalPart : '');
}
alert(precise_round('1.275', 2));
alert(precise_round('1.27499999999999993', 2));
注意,这个函数舍入到最近邻,与零绑定,而IEEE 754建议舍入到最近邻,与偶数绑定,作为浮点运算的默认行为。这样的修改留给读者练习:)
您还可以使用. toprecision()方法和一些自定义代码,无论int部分的长度如何,始终四舍五入到十进制第n位。
function glbfrmt (number, decimals, seperator) {
return typeof number !== 'number' ? number : number.toPrecision( number.toString().split(seperator)[0].length + decimals);
}
你也可以让它成为一个插件,以便更好地使用。
我通常把它添加到我的个人库中,在一些建议和使用@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(十进制),以始终以正确的格式输出数字(具有正确数量的小数)。
差不多就是这样了。好好使用它;)
编辑:增加了负数“更正”功能。