64位浮点数学在JavaScript中,为什么在这种情况下除乘以比乘法更好
这不是关于浮点如何工作的问题。这也是为什么19.95 * 0.1产生19.9000000004的问题。我已经得到了浮点数学并不是一个完美的演示文稿。问题是要问专家他们的直觉为什么这种特殊情况有效。
最近,我想为踏脚滑块的任意数量汇总数量。我有这个代码,
steppedV = Math.round(v / step) * step
因为浮点数学问题,我发现它不是很好。例如v = 19.94
step = 0.1
返回19.90000000000000002
以为我有点不幸
steppedV = Math.round(v / step) / (1 / step)
我 ,对于测试用例,我一直使用它的结果更好。对于与上面相同的输入,我会返回19.9
对于所有未舍入的conse tos tos test步骤值的情况,现在所有这些都可以正常工作。能够真正掌握浮点数学工作方式的人可以解释为什么/(1/ step)产生更准确的结果,而
*步骤没有?因为一个了解浮点数学的人这是直观的吗?我只是很幸运还是作为专家,您是否知道(1 / step)的部门以获得更好的结果?
function test(start, end, inc, step) {
const addRow = makeTable(step, 'div', 'mult');
for (let v = start; v <= end; v += inc) {
const steppedVMult = Math.round(v / step) * step;
const steppedVDiv = Math.round(v / step) / (1 / step);
addRow(v, steppedVDiv, steppedVMult);
}
}
test(0, 2, 0.03, 0.1);
test(0, 0.2, 0.003, 0.01);
test(0, 0.02, 0.0003, 0.001);
test(0, 0.002, 0.00003, 0.0001);
function c(tag, children = [], text = '') {
const e = document.createElement(tag);
e.textContent = text;
children.forEach(c => e.appendChild(c));
return e;
}
function makeTable(...args) {
const makeRow = arr => c('tr', arr.map(v => c('td', [], v)));
const tbody = c('tbody');
const table = c('table', [
c('thead', [makeRow(args)]),
tbody,
]);
document.body.appendChild(table);
return function(...args) {
tbody.appendChild(makeRow(args));
};
}
body { font-family: monospace; }
table { border-collapse: collapse; margin-bottom: 10px }
thead { font-weight: bold; }
td { border: 1px solid #888; padding: 3px; }
This is not a question about how floating point works. Nor is it a question about why 19.95 * 0.1 produces 19.900000000004. I already get that floating point math isn't a perfect presentation. The question is rather to ask an expert their intuition why this particular case works.
Recently I wanted to round numbers to an arbitrary amount for a stepping slider. I had this code
steppedV = Math.round(v / step) * step
I found it's not very good because of floating point math issues. For example v = 19.94
step = 0.1
returns 19.900000000000002
I thought I was kind of out of luck but then just for fun I tried this
steppedV = Math.round(v / step) / (1 / step)
And surprisingly, for the test cases I've been using it's producing better results. For the same inputs as above I get back 19.9
For all my cases that were not rounding to my test step values it's all working now. Can someone who really groks how floating point math works explain why / (1 / step)
produces more accurate results and * step
does not? As someone who understands floating point math is this result intuitive? Am I just getting lucky or as an expert would you have known to do the division of (1 / step) for a better result?
function test(start, end, inc, step) {
const addRow = makeTable(step, 'div', 'mult');
for (let v = start; v <= end; v += inc) {
const steppedVMult = Math.round(v / step) * step;
const steppedVDiv = Math.round(v / step) / (1 / step);
addRow(v, steppedVDiv, steppedVMult);
}
}
test(0, 2, 0.03, 0.1);
test(0, 0.2, 0.003, 0.01);
test(0, 0.02, 0.0003, 0.001);
test(0, 0.002, 0.00003, 0.0001);
function c(tag, children = [], text = '') {
const e = document.createElement(tag);
e.textContent = text;
children.forEach(c => e.appendChild(c));
return e;
}
function makeTable(...args) {
const makeRow = arr => c('tr', arr.map(v => c('td', [], v)));
const tbody = c('tbody');
const table = c('table', [
c('thead', [makeRow(args)]),
tbody,
]);
document.body.appendChild(table);
return function(...args) {
tbody.appendChild(makeRow(args));
};
}
body { font-family: monospace; }
table { border-collapse: collapse; margin-bottom: 10px }
thead { font-weight: bold; }
td { border: 1px solid #888; padding: 3px; }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论