这一行代码把数字四舍五入到小数点后两位。但我得到的数字是这样的: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的使用对我来说很好。
当前回答
通常,十进制舍入是通过缩放完成的: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)。
其他回答
这是一个老话题,但仍然排名靠前的谷歌结果和提供的解决方案共享相同的浮点小数问题。下面是我使用的(非常通用的)函数,感谢MDN:
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));
}
正如我们所看到的,我们没有得到这些问题:
round(1.275, 2); // Returns 1.28
round(1.27499, 2); // Returns 1.27
这个泛型还提供了一些很酷的东西:
round(1234.5678, -2); // Returns 1200
round(1.2345678e+2, 2); // Returns 123.46
round("123.45"); // Returns 123
现在,要回答OP的问题,你必须输入:
round(10.8034, 2).toFixed(2); // Returns "10.80"
round(10.8, 2).toFixed(2); // Returns "10.80"
或者,对于一个更简洁,不那么通用的函数:
function round2Fixed(value) {
value = +value;
if (isNaN(value))
return NaN;
// Shift
value = value.toString().split('e');
value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + 2) : 2)));
// Shift back
value = value.toString().split('e');
return (+(value[0] + 'e' + (value[1] ? (+value[1] - 2) : -2))).toFixed(2);
}
你可以用:
round2Fixed(10.8034); // Returns "10.80"
round2Fixed(10.8); // Returns "10.80"
各种例子和测试(感谢@t-j-克劳德!):
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 naive(value, exp) { if (!exp) { return Math.round(value); } var pow = Math.pow(10, exp); return Math.round(value * pow) / pow; } function test(val, places) { subtest(val, places); val = typeof val === "string" ? "-" + val : -val; subtest(val, places); } function subtest(val, places) { var placesOrZero = places || 0; var naiveResult = naive(val, places); var roundResult = round(val, places); if (placesOrZero >= 0) { naiveResult = naiveResult.toFixed(placesOrZero); roundResult = roundResult.toFixed(placesOrZero); } else { naiveResult = naiveResult.toString(); roundResult = roundResult.toString(); } $("<tr>") .append($("<td>").text(JSON.stringify(val))) .append($("<td>").text(placesOrZero)) .append($("<td>").text(naiveResult)) .append($("<td>").text(roundResult)) .appendTo("#results"); } test(0.565, 2); test(0.575, 2); test(0.585, 2); test(1.275, 2); test(1.27499, 2); test(1234.5678, -2); test(1.2345678e+2, 2); test("123.45"); test(10.8034, 2); test(10.8, 2); test(1.005, 2); test(1.0005, 2); table { border-collapse: collapse; } table, td, th { border: 1px solid #ddd; } td, th { padding: 4px; } th { font-weight: normal; font-family: sans-serif; } td { font-family: monospace; } <table> <thead> <tr> <th>Input</th> <th>Places</th> <th>Naive</th> <th>Thorough</th> </tr> </thead> <tbody id="results"> </tbody> </table> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
我没有找到这个问题的准确解决方案,所以我自己创造了一个:
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
100%的工作! !试一试
<html> <head> <script> function replacePonto(){ var input = document.getElementById('qtd'); var ponto = input.value.split('.').length; var slash = input.value.split('-').length; if (ponto > 2) input.value=input.value.substr(0,(input.value.length)-1); if(slash > 2) input.value=input.value.substr(0,(input.value.length)-1); input.value=input.value.replace(/[^0-9.-]/,''); if (ponto ==2) input.value=input.value.substr(0,(input.value.indexOf('.')+3)); if(input.value == '.') input.value = ""; } </script> </head> <body> <input type="text" id="qtd" maxlength="10" style="width:140px" onkeyup="return replacePonto()"> </body> </html>
通过引用使用此响应:https://stackoverflow.com/a/21029698/454827
我建立了一个函数来获得动态的小数数:
function toDec(num, dec)
{
if(typeof dec=='undefined' || dec<0)
dec = 2;
var tmp = dec + 1;
for(var i=1; i<=tmp; i++)
num = num * 10;
num = num / 10;
num = Math.round(num);
for(var i=1; i<=dec; i++)
num = num / 10;
num = num.toFixed(dec);
return num;
}
这里的工作示例:https://jsfiddle.net/wpxLduLc/
一轮下来
function round_down(value, decPlaces) {
return Math.floor(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}
围捕
function round_up(value, decPlaces) {
return Math.ceil(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}
圆的
function round_nearest(value, decPlaces) {
return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}
合并https://stackoverflow.com/a/7641824/1889449和 https://www.kirupa.com/html5/rounding_numbers_in_javascript.htm谢谢 他们。