首页 > 解决方案 > 为什么我的 HTML 数字输入卡在步骤 0.010000000000000009 上?

问题描述

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

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

<!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>

标签: htmlinput

解决方案


我相信,根据 HTML5 Living Specification,您的<input />元素“遭受步骤不匹配”:

遵循您的案例的规范...

  • step值为0.010000000000000009(来自)parseFloat

  • step-scale-factor价值1永远为<input type="number" />

  • 是属性,step-base即。min1.2

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

  • 回复:“约束验证”,规范说:

    约束验证:当元素有一个allowed-value-step, 并且对由元素给出的字符串应用 the-algorithm-to-convert-a-string-to-a-number 的结果value=""是一个数字,从 中减去的数字step-base不是的整数倍allowed-value-step,该元素正遭受阶跃不匹配。

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

    • 如果元素具有allowed-value-step 数字value=""属性。
      • (所以这只有非空之后,<input/>比如点击一次向上/向下按钮给它一个值1.2
      • ...然后从 (the ) 中减去1.2( the step-base)得到。1.2value=""0
      • 并且0不是整数倍0.010000000000000009
      • 因此,该元素正遭受步不匹配

现在,写下你的发现:

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

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

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

是的,那是因为下一步是-两个浏览器都将显示截断为,但是一旦发生这种情况,我们就会看到浏览器行为的不同:1.2 + 0.0100000000000000091.2100000000000000091.21

  • Firefox 似乎正确地遵守了规范HTMLInputElement.validity.stepMismatchtrue并且由于步进不匹配条件,它设置 并禁用了向上/向下按钮。
  • Chrome 92 没有,使用向上/向下按钮设置其他值仍然会导致HTMLInputElement.validity.stepMismatch === false.

这是一个显示有效性信息的片段:

<!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.2, 1.21, 1.22, 1.23, ..., 1.28, to 1.29),尽管它从不报告stepIsmatch: true
  • 在 Firefox 中,它让我在设置之前单击向上按钮 1 次(1.21.21stepMismatch: true

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


有趣的是,Number浏览器中的类型似乎能够在0.010000000000000009没有任何迹象的 IEEE 754 舍入(Python 同上)的情况下准确表示,而 C#/.NET 的Single(32 位)和Double(64 位)浮点类型既窒息又给出我相当糟糕的近似值。


推荐阅读