【问题标题】:Why does my HTML number input get stuck with step 0.010000000000000009?为什么我的 HTML 数字输入卡在步骤 0.010000000000000009 上?
【发布时间】:2021-10-18 01:49:34
【问题描述】:

当我使用step="0.010000000000000009" 创建 HTML <input type="number"/> 时。我只能单击按钮增加一次值以填写min值,然后第一次增加一次步长值,然后它会卡在这个值上,进一步点击没有效果。我只能用min="1.2" max="1.3" 重现这个。

minmaxstep 的所有其他组合我尝试允许多次单击该按钮,直到它在定义的步骤中达到最大值。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>input with decimal step</title>
  </head>
  <body>
    <input type="number" min="1.2" max="1.3" step="0.010000000000000009"/>
  </body>
</html>

【问题讨论】:

  • Firefox 让您在卡住之前单击两次。
  • Chrome 中没有复制。如果这只是 FF,则可能需要提交错误报告。
  • 我想到了浮点运算。
  • @Dominik 我的问题不够精确,已编辑
  • 我不确定这一定是 Firefox 中的一个 bug,更多的是 Chrome 更加宽容。根据 MDN,max 值(如果指定)必须等于 min + ( n * step ) - 如果我正确阅读了他们的(不完全清楚)评论:developer.mozilla.org/en-US/docs/Web/HTML/Attributes/step

标签: html input


【解决方案1】:

我相信,根据 HTML5 Living Specification,您的 &lt;input /&gt; 元素“存在步骤不匹配”:

遵循 w.r.t. 的规范。你的情况...

  • step 的值为 0.010000000000000009(来自 parseFloat)。

  • 对于&lt;input type="number" /&gt;step-scale-factor 的值始终为 1

  • step-basemin 属性,即1.2

  • allowed-value-stepstep * step-scale-factor1 * 0.010000000000000009 === 0.010000000000000009

  • Re:“约束验证”,规范是这样说的:

    约束验证:当元素有一个allowed-value-step,并且应用-algorithm-to-convert-a-string-to-a-number 到由元素的value="" 是一个数字,从step-base 中减去的数字不是allowed-value-step 的整数倍,该元素存在步长不匹配。

    我会把它改写成这个......:

    • 如果元素具有allowed-value-step 数字value=""属性。
      • (所以这只是&lt;input/&gt; 不为空,例如单击向上/向下按钮一次 赋予它1.2 的值)
      • ...然后从1.2value="")中减去1.2step-base)得到0
      • 0不是0.010000000000000009的整数倍。
      • 因此元素存在步长不匹配

现在,w.r.t.你的发现:

我只能点击一次按钮增加值填写min

是的,这遵循 HTML5 规范:初始 value="" 为空,因此浏览器将选择 下一个有效的最大值,即 min="1.2" 值。

然后第一次只增加一次步长值

是的,这是因为下一步步骤是1.2 + 0.010000000000000009,即1.210000000000000009 - 这两个浏览器都会将显示截断为1.21,但是一旦发生这种情况 我们发现浏览器行为有所不同:

  • Firefox 似乎正确地符合规范,它将HTMLInputElement.validity.stepMismatch 设置为true,并由于步进不匹配情况而禁用向上/向下按钮。
  • Chrome 92 没有,使用向上/向下按钮设置其他值仍会导致 HTMLInputElement.validity.stepMismatch === false

这是一个显示有效性信息的 sn-p:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>input with decimal step</title>
  </head>
  <body>
    <input id="inp" type="number" min="1.2" max="1.3" step="0.010000000000000009" />

    <ul id="eventsList"></ul>

    <script>
    const inp = document.getElementById('inp');
    const ul  = document.getElementById('eventsList');

    inp.addEventListener( 'input', logInfo );
    inp.addEventListener( 'change', logInfo );
    inp.addEventListener( 'click', logInfo );

    function logInfo( e ) {
        const li = document.createElement('li');
        li.textContent = e.type + ". Value: " + inp.value + ", valid: " + inp.validity.valid + ", stepMismatch: " + inp.validity.stepMismatch;
        ul.appendChild( li );
    }
    </script>

  </body>
</html>
  • 在 Chrome 中,它让我在停止之前单击向上按钮 10 次(1.21.211.221.23、...、1.281.29)它从不报告stepIsmatch: true
  • 在 Firefox 中,它允许我在设置 stepMismatch: true 之前单击向上按钮 1 次(1.21.21)。

我的钱花在 Chrome 上做他们自己的事,因为他们对规范的解释(或至少是他们的实施)更加宽容,并且在 @987654372 时不太可能导致最终用户的挫败感@ 被设置为一个奇怪的值。


有趣的是,浏览器中的 Number 类型似乎能够准确地表示 0.010000000000000009 而无需任何 IEEE 754 舍入(Python 同上),而 C#/.NET 的 Single(32 位)和 @ 987654376@(64 位)浮点类型既窒息又给了我相当糟糕的近似值。

【讨论】:

    猜你喜欢
    • 2016-11-03
    • 1970-01-01
    • 2017-05-22
    • 2016-04-17
    • 2022-11-08
    • 2012-08-31
    • 1970-01-01
    • 1970-01-01
    • 2017-01-15
    相关资源
    最近更新 更多