为什么10000000000000.126.toString()
1000000000000.127和100000000000.126.toString()
没有?
我认为它必须与Js中的Number的最大值有关(根据this SO question),但这与浮点运算有何关系?
我问,因为我写了这个函数来使用数千个分隔符格式化数字,并希望防止这种情况。
function th(n,sep) {
sep = sep || '.';
var dec = n.toString().split(/[,.]/),
nArr = dec[0].split(''),
isDot = /\./.test(sep);
return function tt(n) {
return n.length > 3 ?
tt(n.slice(0,n.length-3)).concat(n.slice(n.length-3).join('')) :
[n.join('')]
;
}(nArr)
.join(sep)
+ (dec[1] ? (isDot?',':'.') + dec[1] : '');
}
sep1000(10000000000000.126); //=> 10.000.000.000.000,127
sep1000(1000000000000.126); //=> 1.000.000.000.000,126
答案 0 :(得分:7)
因为并非所有数字都可以用浮点精确表示(JavaScript使用双精度64位格式IEEE 754数字),所以会出现舍入错误。例如:
alert(0.1 + 0.2); // "0.30000000000000004"
存储有限的所有编号系统(例如,所有编号系统)都存在此问题,但您和我习惯于处理我们的十进制系统(无法准确表示“三分之一”),因此对某些系统感到惊讶计算机使用的浮点格式无法准确表示的不同值。这就是为什么你会看到越来越多的“十进制”样式类型(Java有BigDecimal
,C#有decimal
等),它们使用我们的数字表示形式(at成本)因此对于四舍五入需要更紧密地符合我们期望的应用程序(例如金融应用程序)非常有用。
更新:我还没有尝试过,但您可以通过在获取字符串之前稍微操纵值来解决此问题。例如,这适用于您的具体示例(live copy):
代码:
function display(msg) {
var p = document.createElement('p');
p.innerHTML = msg;
document.body.appendChild(p);
}
function preciseToString(num) {
var floored = Math.floor(num),
fraction = num - floored,
rv,
fractionString,
n;
rv = String(floored);
n = rv.indexOf(".");
if (n >= 0) {
rv = rv.substring(0, n);
}
fractionString = String(fraction);
if (fractionString.substring(0, 2) !== "0.") {
return String(num); // punt
}
rv += "." + fractionString.substring(2);
return rv;
}
display(preciseToString(10000000000000.126));
结果:
10000000000000.126953125
......当然,你可以根据自己的意愿将其截断。当然,重要的是要注意10000000000000.126953125 != 10000000000000.126
。但是我认为这艘船已经航行(例如,Number
已经包含了一个不精确的值),因为你看到了.127
。我看不出有任何方法可以让你知道原文只有三个地方,而不是Number
。
我不是说以上 以任何方式 可靠,你必须真正通过步伐来证明它(也就是说,我那我没做什么stoopid。再说一次,既然你不知道精度在哪里结束,我不确定它有多大帮助。
答案 1 :(得分:2)
它是浮点数可存储的最大有效十进制数。
如果查看http://en.wikipedia.org/wiki/IEEE_754-2008,可以看到双精度浮点数(binary64)可以存储大约16(15.95)个十进制数字。
如果您的数字包含更多数字,则实际上会失去精确度,例如您的样本。