在JavaScript中用两位小数格式化数字
我有这个代码行,我的数字四位小数。 但是我得到这样的数字:10.8,2.4等。这些不是我的两位小数的想法,所以我怎么能改善以下?
Math.round(price*Math.pow(10,2))/Math.pow(10,2);
我需要像10.80,2.40等数字。使用jQuery对我来说没问题。
要使用定点符号格式化数字,您可以简单地使用toFixed方法:
(10.8).toFixed(2); // "10.80" var num = 2.4; alert(num.toFixed(2)); // "2.40"
注意toFixed()
返回一个string。
重要提示 :注意toFixed实际上并不是实际的四舍五入,对于90%的情况,它会返回四舍五入的值,但是在很多情况下它并不实际工作。 在你的控制台试试这个:
2.005.toFixed(2)
你会得到错误的答案
有没有自然的方式获得在javascript中的小数舍入,你将需要自己的polyfill或使用库。 你可以看看这个https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round的; mozilla的polyfill
这是一个古老的话题,但仍然排名第一的谷歌的结果和提供的解决scheme共享相同的浮点小数的问题。 下面是我使用的(非常通用的)函数, 感谢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的问题,必须input:
round(10.8034, 2).toFixed(2); // Returns "10.80" round(10.8, 2).toFixed(2); // Returns "10.80"
或者,为了更简洁,不那么通用的function:
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"
各种例子和testing(感谢@ tj-crowder !):
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>
我通常把这个添加到我的个人图书馆,经过一些build议和使用@TIMINeutron解决scheme,并使其适应小数的长度,然后,这一个最合适:
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的回答提出了一个解决scheme:
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(他想)。
我的最终解决scheme如下:
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); }
正如你所看到的,我不得不添加一点“修正”(这不是什么,但是因为Math.round是有损的 – 你可以在jsfiddle.net上检查它 – 这是我知道如何“修复“它)。 它将已经填充的数字加上0.001,所以在十进制数值的右边加上1
3 3 0
s。 所以它应该是安全的使用。
之后,我添加.toFixed(decimal)
以始终以正确的格式(具有正确的小数)输出数字。
所以这是非常多的。 用得好;)
编辑:增加function的“纠正”的负数。
toFixed(n)在小数点后面提供n长度; toPrecision(x)提供x总长度。
使用下面的这个方法
// Example: toPrecision(4) when the number has 7 digits (3 before, 4 after) // It will round to the tenths place num = 500.2349; result = num.toPrecision(4); // result will equal 500.2
如果你想要这个号码被固定使用
result = num.toFixed(2);
一种方法是100%确定你得到一个2位小数的数字:
(Math.round(num*100)/100).toFixed(2)
如果这会导致舍入错误,那么可以使用以下内容,正如James在他的评论中所解释的那样:
(Math.round((num * 1000)/10)/100).toFixed(2)
我没有find这个问题的准确解决scheme,所以我创build了自己的:
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
@heridev和我在jQuery中创build了一个小函数。
你可以尝试下一步:
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 }); });
在线演示:
浮点值的问题在于它们试图用固定数量的位来表示无限量(连续)的值。 所以很自然的,一定会有一些损失,你会被一些价值所吸引。
当一台电脑存储1.275浮点值时,实际上并不记得是1.275还是1.27499999999999993,甚至是1.27500000000000002。 这些值在四舍五入到小数点后应该给出不同的结果,但是它们不会,因为对于计算机来说,它们在存储为浮点值后看起来完全相同 ,并且没有办法恢复丢失的数据。 任何进一步的计算只会积累这样的不精确。
所以,如果精度很重要,你必须从一开始就避免浮点值。 最简单的select是
- 使用专门的图书馆
- 使用string来存储和传递值(伴随string操作)
- 使用整数(例如,您可以传递大约百分之几的实际价值,例如以美分而不是以美元为单位的金额)
例如,当使用整数来存储百分数时,find实际值的函数非常简单:
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));
用string,你需要四舍五入,但它仍然是可pipe理的:
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 754build议将四舍五入到最近的关系,甚至作为浮点运算的默认行为。 这样的修改留给读者的练习:)
这是一个简单的
function roundFloat(num,dec){ var d = 1; for (var i=0; i<dec; i++){ d += "0"; } return Math.round(num * d) / d; }
使用像alert(roundFloat(1.79209243929,4));
的jsfiddle
将您的十进制值toFixed(x)
,然后使用toFixed(x)
作为您的预期数字。
function parseDecimalRoundAndFixed(num,dec){ var d = Math.pow(10,dec); return (Math.round(num * d) / d).toFixed(dec); }
呼叫
parseDecimalRoundAndFixed(10.800243929,4)=> 10.80 parseDecimalRoundAndFixed(10.807243929,2)=> 10.81
将以下内容放在全局范围内:
Number.prototype.getDecimals = function ( decDigCount ) { return this.toFixed(decDigCount); }
然后尝试 :
var a = 56.23232323; a.getDecimals(2); // will return 56.23
更新
请注意, toFixed()
只能在0-20
之间的小数位数工作,即a.getDecimals(25)
可能会产生一个JavaScript错误,所以为了适应,你可以添加一些额外的检查即
Number.prototype.getDecimals = function ( decDigCount ) { return ( decDigCount > 20 ) ? this : this.toFixed(decDigCount); }
我正在解决修改器的问题。 仅支持2位小数。
$(function(){ //input number only. convertNumberFloatZero(22); // output : 22.00 convertNumberFloatZero(22.5); // output : 22.50 convertNumberFloatZero(22.55); // output : 22.55 convertNumberFloatZero(22.556); // output : 22.56 convertNumberFloatZero(22.555); // output : 22.55 convertNumberFloatZero(22.5541); // output : 22.54 convertNumberFloatZero(22222.5541); // output : 22,222.54 function convertNumberFloatZero(number){ if(!$.isNumeric(number)){ return 'NaN'; } var numberFloat = number.toFixed(3); var splitNumber = numberFloat.split("."); var cNumberFloat = number.toFixed(2); var cNsplitNumber = cNumberFloat.split("."); var lastChar = splitNumber[1].substr(splitNumber[1].length - 1); if(lastChar > 0 && lastChar < 5){ cNsplitNumber[1]--; } return Number(splitNumber[0]).toLocaleString('en').concat('.').concat(cNsplitNumber[1]); }; });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
(Math.round((10.2)*100)/100).toFixed(2)
这应该产生: 10.20
(Math.round((.05)*100)/100).toFixed(2)
这应该产生: 0.05
(Math.round((4.04)*100)/100).toFixed(2)
这应该产生: 4.04
等等
Number(((Math.random() * 100) + 1).toFixed(2))
这将返回从1到100的随机数四舍五入到小数点后两位。
/*Due to all told stuff. You may do 2 things for different purposes: When showing/printing stuff use this in your alert/innerHtml= contents: YourRebelNumber.toFixed(2)*/ var aNumber=9242.16; var YourRebelNumber=aNumber-9000; alert(YourRebelNumber); alert(YourRebelNumber.toFixed(2)); /*and when comparing use: Number(YourRebelNumber.toFixed(2))*/ if(YourRebelNumber==242.16)alert("Not Rounded"); if(Number(YourRebelNumber.toFixed(2))==242.16)alert("Rounded"); /*Number will behave as you want in that moment. After that, it'll return to its defiance. */
这非常简单,并且与其他任何一个一样工作:
function parseNumber(val, decimalPlaces) { if (decimalPlaces == null) decimalPlaces = 0 var ret = Number(val).toFixed(decimalPlaces) return Number(ret) }
由于toFixed()只能在数字上被调用,而不幸的是返回一个string,所以在两个方向上都会为你parsing。 你可以传递一个string或一个数字,并且每次都得到一个数字! 调用parseNumber(1.49)会给你1,而parseNumber(1.49.2)会给你1.50。 就像他们最好的!
您也可以使用.toPrecision()
方法和一些自定义代码,并且无论int部分的长度如何,总是舍入到.toPrecision()
个十进制数字。
function glbfrmt (number, decimals, seperator) { return typeof number !== 'number' ? number : number.toPrecision( number.toString().split(seperator)[0].length + decimals); }
你也可以把它作为一个更好的使用插件。
Number(Math.round(1.005+'e2')+'e-2'); // 1.01
这对我工作: JavaScript中四舍五入的小数
通过引用使用此响应: https : //stackoverflow.com/a/21029698/454827
我build立一个函数来获取dynamic数字的小数:
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/
parse = function (data) { data = Math.round(data*Math.pow(10,2))/Math.pow(10,2); if (data != null) { var lastone = data.toString().split('').pop(); if (lastone != '.') { data = parseFloat(data); } } return data; }; $('#result').html(parse(200)); // output 200 $('#result1').html(parse(200.1)); // output 200.1 $('#result2').html(parse(200.10)); // output 200.1 $('#result3').html(parse(200.109)); // output 200.11
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script> <div id="result"></div> <div id="result1"></div> <div id="result2"></div> <div id="result3"></div>
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>