在 JavaScript 中,从浮点数转换为字符串时,我怎样才能得到小数点后的 2 位数字?例如,0.34 而不是 0.3445434。
var result = Math.round(original*100)/100;
The specifics,以防代码不言自明。
编辑:...或仅使用 Tim Büthe 建议的 toFixed
。忘了那个,谢谢(和赞成)提醒:)
toFixed()
将模仿类似 printf()
在 C 中所做的事情。但是,toFixed()
和 Math.round()
会以不同的方式处理舍入。在这种情况下,toFixed()
将具有与 Math.floor()
相同的效果(假设您事先将原始值乘以 10^n,并使用 n 位调用 toFixed()
)。答案的“正确性”在很大程度上取决于 OP 想要什么,并且两者都以自己的方式“正确”。
使用 toFixed()
时要小心:
首先,使用数字的二进制表示对数字进行四舍五入,这可能会导致意外行为。例如
(0.595).toFixed(2) === '0.59'
而不是 '0.6'
。
其次,toFixed()
存在 IE 错误。在 IE(至少到版本 7,没有检查 IE8)中,以下情况成立:
(0.9).toFixed(0) === '0'
遵循 kkyy 的建议或使用自定义 toFixed()
函数可能是个好主意,例如
function toFixed(value, precision) {
var power = Math.pow(10, precision || 0);
return String(Math.round(value * power) / power);
}
.toFixed()
方法,这将增加所需的精度,例如:return (Math.round(value * power) / power).toFixed(precision);
并将值作为字符串返回。否则,对于较小的小数,20 的精度将被忽略
toFixed
的一个注意事项:请注意,提高精度可能会产生意想不到的结果:(1.2).toFixed(16) === "1.2000000000000000"
,而 (1.2).toFixed(17) === "1.19999999999999996"
(在 Firefox/Chrome 中;在 IE8 中,由于 IE8 内部可以提供的精度较低,后者不成立)。
(0.598).toFixed(2)
也不会产生 0.6
。它产生 0.60
:)
(0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)
。
还有一个需要注意的问题是,toFixed()
会在数字末尾产生不必要的零。例如:
var x=(23-7.37)
x
15.629999999999999
x.toFixed(6)
"15.630000"
想法是使用 RegExp
清理输出:
function humanize(x){
return x.toFixed(6).replace(/\.?0*$/,'');
}
RegExp
匹配尾随的零(以及可选的小数点),以确保它也适合整数。
humanize(23-7.37)
"15.63"
humanize(1200)
"1200"
humanize(1200.03)
"1200.03"
humanize(3/4)
"0.75"
humanize(4/3)
"1.333333"
var x = 0.3445434
x = Math.round (x*100) / 100 // this will make nice rounding
所有这些使用乘法器浮动的解决方案都存在问题。不幸的是,kyyy 和 Christoph 的解决方案都是错误的。
请测试您的代码 551.175 的 2 位小数 - 它将四舍五入为 551.17 而它应该是 551.18 !但如果你测试前。 451.175 没问题 - 451.18。所以乍一看很难发现这个错误。
问题在于乘法:尝试 551.175 * 100 = 55117.49999999999 (ups!)
所以我的想法是在使用 Math.round() 之前用 toFixed() 处理它;
function roundFix(number, precision)
{
var multi = Math.pow(10, precision);
return Math.round( (number * multi).toFixed(precision + 1) ) / multi;
}
toFixed
也受到影响 - (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)
...无论使用哪种方法,最好在四舍五入之前添加一个 epsilon。
我猜这里的关键是先正确四舍五入,然后你可以将它转换为字符串。
function roundOf(n, p) {
const n1 = n * Math.pow(10, p + 1);
const n2 = Math.floor(n1 / 10);
if (n1 >= (n2 * 10 + 5)) {
return (n2 + 1) / Math.pow(10, p);
}
return n2 / Math.pow(10, p);
}
// All edge cases listed in this thread
roundOf(95.345, 2); // 95.35
roundOf(95.344, 2); // 95.34
roundOf(5.0364342423, 2); // 5.04
roundOf(0.595, 2); // 0.60
roundOf(0.335, 2); // 0.34
roundOf(0.345, 2); // 0.35
roundOf(551.175, 2); // 551.18
roundOf(0.3445434, 2); // 0.34
现在您可以使用 toFixed(p) 安全地格式化该值。因此,对于您的具体情况:
roundOf(0.3445434, 2).toFixed(2); // 0.34
如果你想要没有圆形的字符串,你可以使用这个正则表达式(也许不是最有效的方法......但真的很容易)
(2.34567778).toString().match(/\d+\.\d{2}/)[0]
// '2.34'
function trimNumber(num, len) {
const modulu_one = 1;
const start_numbers_float=2;
var int_part = Math.trunc(num);
var float_part = String(num % modulu_one);
float_part = float_part.slice(start_numbers_float, start_numbers_float+len);
return int_part+'.'+float_part;
}
return float_part ? int_part+'.'+float_part : int_part;
,否则如果您传递 Integer,它会返回最后带有点的数字(示例输入:2100
,输出:2100.
)
也许您还需要小数分隔符?这是我刚刚制作的一个函数:
function formatFloat(num,casasDec,sepDecimal,sepMilhar) {
if (num < 0)
{
num = -num;
sinal = -1;
} else
sinal = 1;
var resposta = "";
var part = "";
if (num != Math.floor(num)) // decimal values present
{
part = Math.round((num-Math.floor(num))*Math.pow(10,casasDec)).toString(); // transforms decimal part into integer (rounded)
while (part.length < casasDec)
part = '0'+part;
if (casasDec > 0)
{
resposta = sepDecimal+part;
num = Math.floor(num);
} else
num = Math.round(num);
} // end of decimal part
while (num > 0) // integer part
{
part = (num - Math.floor(num/1000)*1000).toString(); // part = three less significant digits
num = Math.floor(num/1000);
if (num > 0)
while (part.length < 3) // 123.023.123 if sepMilhar = '.'
part = '0'+part; // 023
resposta = part+resposta;
if (num > 0)
resposta = sepMilhar+resposta;
}
if (sinal < 0)
resposta = '-'+resposta;
return resposta;
}
使用乘法或除法无法避免以 x.xx5 作为实际值的价格舍入不一致。如果您需要在客户端计算正确的价格,您应该将所有金额保留为美分。这是由于 JavaScript 中数值的内部表示的性质。请注意,Excel 也存在同样的问题,因此大多数人不会注意到由这种现象引起的小错误。但是,当您将大量计算值相加时,错误可能会累积,围绕这一点有一个完整的理论,涉及计算顺序和其他方法以最小化最终结果中的错误。为了强调十进制值的问题,请注意 0.1 + 0.2 在 JavaScript 中并不完全等于 0.3,而 1 + 2 等于 3。
/** don't spend 5 minutes, use my code **/
function prettyFloat(x,nbDec) {
if (!nbDec) nbDec = 100;
var a = Math.abs(x);
var e = Math.floor(a);
var d = Math.round((a-e)*nbDec); if (d == nbDec) { d=0; e++; }
var signStr = (x<0) ? "-" : " ";
var decStr = d.toString(); var tmp = 10; while(tmp<nbDec && d*tmp < nbDec) {decStr = "0"+decStr; tmp*=10;}
var eStr = e.toString();
return signStr+eStr+"."+decStr;
}
prettyFloat(0); // "0.00"
prettyFloat(-1); // "-1.00"
prettyFloat(-0.999); // "-1.00"
prettyFloat(0.5); // "0.50"
我使用此代码来格式化浮点数。它基于 toPrecision()
,但去除了不必要的零。我欢迎有关如何简化正则表达式的建议。
function round(x, n) {
var exp = Math.pow(10, n);
return Math.floor(x*exp + 0.5)/exp;
}
使用示例:
function test(x, n, d) {
var rounded = rnd(x, d);
var result = rounded.toPrecision(n);
result = result.replace(/\.?0*$/, '');
result = result.replace(/\.?0*e/, 'e');
result = result.replace('e+', 'e');
return result;
}
document.write(test(1.2000e45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2000e+45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2340e45, 3, 2) + '=' + '1.23e45' + '<br>');
document.write(test(1.2350e45, 3, 2) + '=' + '1.24e45' + '<br>');
document.write(test(1.0000, 3, 2) + '=' + '1' + '<br>');
document.write(test(1.0100, 3, 2) + '=' + '1.01' + '<br>');
document.write(test(1.2340, 4, 2) + '=' + '1.23' + '<br>');
document.write(test(1.2350, 4, 2) + '=' + '1.24' + '<br>');
countDecimals = value => { if (Math.floor(value) === value) return 0;让 stringValue = value.toString().split(".")[1]; if (stringValue) { return value.toString().split(".")[1].length ? value.toString().split(".")[1].length : 0; } 其他 { 返回 0; } }; formatNumber=(ans)=>{ let decimalPlaces = this.countDecimals(ans);答案 = 1 * 答案; if (decimalPlaces !== 0) { 让 onePlusAns = ans + 1;让 decimalOnePlus = this.countDecimals(onePlusAns); if (decimalOnePlus < decimalPlaces) { ans = ans.toFixed(decimalPlaces - 1).replace(/\.?0*$/, ""); } else { 让 tenMulAns = ans * 10;让 decimalTenMul = this.countDecimals(tenMulAns); if (decimalTenMul + 1 < decimalPlaces) { ans = ans.toFixed(decimalPlaces - 1).replace(/\.?0*$/, ""); } } } }
我只是将值加 1 并计算原始值和附加值中存在的十进制数字。如果在添加比原始十进制数字少一位后找到十进制数字,我只需使用(原始小数 - 1)调用 toFixed()。我还通过将原始值乘以 10 进行检查,并遵循相同的逻辑,以防加一不会减少多余的小数位。在 JS 中处理浮点数舍入的简单解决方法。在我尝试过的大多数情况下都有效。
var x = 5.036432346; var y = x.toFixed(2) + 100;
y
将等于"5.03100"
(0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)
...