数字输入错误地接受带小数位的浮点数

菲尔294

<form>
  <input type="number" step="1" required>
  <input type="submit">
</form>

在上面的代码段中,如果您插入

0.0000001

输入数字时,您不能提交表单:“ step”属性可以防止这种情况。

但是如果你插入

0.00000001

它可以在Chrome / Chromium中使用!为什么在验证输入时似乎只读取前七个小数位?是否在任何地方对此进行了记录,并且我可以做些什么来防止这种情况发生?

我测试了Firefox,它不接受任何此类值。

为了澄清起见0.30000000000000004 === 0.1+0.2,这里不是常见的陷阱,因为这仅发生在小数点后16位。上面的输入值失败,保留8位小数。

朱利安·格雷戈尔

虽然这肯定是您所拥有数字的错误,但实际上可以防止其他步骤/值组出现问题。分数舍入存在一些核心问题,因此要进行完美的步骤验证并非那么容易,至少不是那样精确。实际上,如果您查看Firefox源代码,则可以找到以下注释https://dxr.mozilla.org/mozilla-central/source/dom/html/HTMLInputElement.cpp#4654

在处理小数时,下面可能会出现舍入问题,但是在ECMAScript为我们提供十进制数类型之前,我们可以忽略它。

因此,问题不仅仅与Chrome有关。但是,让我们从您描述的错误开始。如果查看Chromium源代码,则可以看到在step_range处理中,有一个名为AcceptableError的方法,该方法可以调整值和针对该步骤调整的值之间的差。参见https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/forms/step_range.cc?l=60此可接受的错误定义为:

the step value / 2^24 (in the source code UINT64_C(1) << FLT_MANT_DIG) 

这给出了第一步:

1 / 16777216 = 0.000000059604645

因此,在您的原始示例中,即使该数字不具有余数,该数字也将有效。计算余数的公式为:

value - step * Math.abs(Math.round(value / step));

因此,例如,如果您输入2.000000059604644,则余数为:

  2.000000059604644 - 1 * Math.abs(Math.round(2.000000059604644))
= 2.000000059604644 - 2
= 0.000000059604644 

0.000000059604644低于0.000000059604645,因此它将进行验证。2.000000059604646不会。

<form>
  <input type="number" step="1" required>
  <input type="submit">
</form>

您可以尝试使用更大的数字,例如,采取167772167的步骤。这将产生一个可接受的错误:

16777217 / 16777216 = 1.000000059604645

值16777218的余数为:

  16777218 - 16777217 * Math.abs(Math.round(1.000000059604645 ))
= 16777218 - 16777217
= 1

<form>
  <input type="number" step="16777217" required>
  <input type="submit">
</form>

该误差在您可接受的错误1下,因此它将进行验证。

所以这是错误。它允许复仇的目的是容忍某些步骤和值,这些步骤和值由于十进制运算的精度损失而无法在应有的时间进行验证。而在Firefox之类的浏览器中,这正是发生的情况。某些值/步骤对在何时应验证。

例如,采取853.2394的步长和495714162280.48785的值。这肯定可以验证,因为:

495714162280.48785 / 853.2394 = 580978987

如果您在Firefox中尝试过,它将无法验证。但是在Chrome中,由于第一种情况下会导致错误的容忍度,因此它可以进行验证。

<form>
  <input type="number" step="853.2394" required>
  <input type="submit">
</form>

因此,最终,此错误与小数运算的已知问题有关,这并不精确。经典示例是0.1 + 0.2 = 0.30000000000000004。后台发生的事情更加复杂和精确,但是处理小数计算的问题会导致这些问题,并使其很难在每种情况下都避免。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在打印浮点数时,如何更精确地打印小数位?

如何计算浮点数的小数位?

转换浮点数并保持小数位

MariaDB默认浮点数不能包含小数位

JavaScript格式的浮点数小数位数

带浮点数/小数的字母数字

printf传递给变量的精度为浮点数(小数位数)的浮点数

如何可靠地将浮点数格式化为Haxe中指定的小数位数

计算Swift中浮点数(或小数)的小数位数

基本浮点数和双精度支持多少个小数位?

将浮点数格式化为n个小数位,且不包含尾随零

将浮点数格式化为2个小数位

如何打印浮点数到n个小数位,包括尾随0?

如何将浮点数打印到n个小数位(包括尾随0)?

如何将具有 n 个小数位的整数转换为浮点数

在SwiftUI中显示具有指定小数位的浮点数

如何计算具有给定小数位的浮点数?

将浮点数四舍五入到与乘数相同的小数位

如何使用sprintf输出小于1且没有前导小数位的浮点数?

如何将小数位数转换为相同单位的浮点数?

只显示我的浮点数到某个小数位-Swift

SQL 打印带有大小数位的浮点数

如何计算浮点数和双精度数的小数位数?

我如何确定应使用多少小数位,用于c中的浮点数

将列表从 str 转换为带有超过 2 个小数位的浮点数

如何在python中生成至少20个小数位的种子随机浮点数?

将浮点数四舍五入到最小数并保留几个小数位

在Java中,如何删除整数形式的输出double的小数位,而当其为浮点数时保留它们?

在Inno Setup Pascal脚本中将浮点数四舍五入到N个小数位