假设我有一个值15.7784514,我想把它显示为15.77,没有舍入。
var num = parseFloat(15.7784514);
document.write(num.toFixed(1)+"<br />");
document.write(num.toFixed(2)+"<br />");
document.write(num.toFixed(3)+"<br />");
document.write(num.toFixed(10));
结果:
15.8
15.78
15.778
15.7784514000
如何显示15.77?
我知道已经有一些工作示例,但我认为值得提出我的String。对于固定等价物,有些人可能会发现它很有用。
这是我的toFixed替代方案,它不舍入数字,只是根据给定的精度截断它或加零。对于超长的数字,当精度太长时,它使用JS内置的舍入。
函数适用于我在堆栈上发现的所有有问题的数字。
function toFixedFixed(value, precision = 0) {
let stringValue = isNaN(+value) ? '0' : String(+value);
if (stringValue.indexOf('e') > -1 || stringValue === 'Infinity' || stringValue === '-Infinity') {
throw new Error('To large number to be processed');
}
let [ beforePoint, afterPoint ] = stringValue.indexOf('.') > -1 ? stringValue.split('.') : [ stringValue, ''];
// Force automatic rounding for some long real numbers that ends with 99X, by converting it to string, cutting off last digit, then adding extra nines and casting it on number again
// e.g. 2.0199999999999996: +('2.019999999999999' + '9999') will give 2.02
if (stringValue.length >= 17 && afterPoint.length > 2 && +afterPoint.substr(afterPoint.length - 3) > 995) {
stringValue = String(+(stringValue.substr(0, afterPoint.length - 1) + '9'.repeat(stringValue.split('.').shift().length + 4)));
[ beforePoint, afterPoint ] = String(stringValue).indexOf('.') > -1 ? stringValue.split('.') : [ stringValue, ''];
}
if (precision === 0) {
return beforePoint;
} else if (afterPoint.length > precision) {
return `${beforePoint}.${afterPoint.substr(0, precision)}`;
} else {
return `${beforePoint}.${afterPoint}${'0'.repeat(precision - afterPoint.length)}`;
}
}
请记住,精度可能无法正确处理长度为18或更大的数字,例如64位Chrome将四舍五入或添加“e+”/“e-”以保持数字的长度为18。
如果你想对实数进行运算,用Math乘以它会更安全。先根号(10,精度),进行计算,然后按乘数的值潜水结果。
例子:
0.06 + 0.01等于0.0699999999999999999,每个格式化函数
这不是四舍五入会截断为0.06以达到精度2。
但如果你用乘数和除法器(0.06 * 100 + 0.01 * 100)/ 100执行同样的操作,你会得到0.07。
这就是为什么在javascript中处理实数时使用乘数/除法是如此重要,特别是当你计算金钱时…
Gumbo的第二个解决方案,使用正则表达式,可以工作,但由于使用正则表达式,速度较慢。由于浮点数不精确,Gumbo的第一个解决方案在某些情况下会失败。有关演示和基准测试,请参阅JSFiddle。在我目前使用的3.30 GHz Intel酷睿i5-2500 CPU系统上,第二个解决方案每次调用大约需要1636纳秒。
我所编写的解决方案包括添加一个小的补偿来处理浮点的不精确性。它基本上是瞬时的,即在纳秒的数量级上。我每次调用的时间是2纳秒,但JavaScript计时器不是非常精确或粒度。下面是JS的Fiddle和代码。
function toFixedWithoutRounding (value, precision)
{
var factorError = Math.pow(10, 14);
var factorTruncate = Math.pow(10, 14 - precision);
var factorDecimal = Math.pow(10, precision);
return Math.floor(Math.floor(value * factorError + 1) / factorTruncate) / factorDecimal;
}
var values = [1.1299999999, 1.13, 1.139999999, 1.14, 1.14000000001, 1.13 * 100];
for (var i = 0; i < values.length; i++)
{
var value = values[i];
console.log(value + " --> " + toFixedWithoutRounding(value, 2));
}
for (var i = 0; i < values.length; i++)
{
var value = values[i];
console.log(value + " --> " + toFixedWithoutRounding(value, 4));
}
console.log("type of result is " + typeof toFixedWithoutRounding(1.13 * 100 / 100, 2));
// Benchmark
var value = 1.13 * 100;
var startTime = new Date();
var numRun = 1000000;
var nanosecondsPerMilliseconds = 1000000;
for (var run = 0; run < numRun; run++)
toFixedWithoutRounding(value, 2);
var endTime = new Date();
var timeDiffNs = nanosecondsPerMilliseconds * (endTime - startTime);
var timePerCallNs = timeDiffNs / numRun;
console.log("Time per call (nanoseconds): " + timePerCallNs);