64位浮点数学在JavaScript中,为什么在这种情况下除乘以比乘法更好

发布于 2025-02-13 19:30:26 字数 1940 浏览 0 评论 0原文

这不是关于浮点如何工作的问题。这也是为什么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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文