新垣结衣
小狐狸
小狐狸
  • UID55997
  • 注册日期2017-09-25
  • 最后登录2019-10-16
  • 发帖数87
  • 经验98枚
  • 威望0点
  • 贡献值60点
  • 好评度8点
  • 忠实会员
  • 社区居民
阅读:925回复:10

关于 <input type="number" value="123456789123456789" />

楼主#
更多 发布于:2017-11-16 18:27
在火狐里看是 123456789123457000 ,有谁知道这个转换的逻辑?
aaaa007cn
千年狐狸
千年狐狸
  • UID23968
  • 注册日期2008-05-03
  • 最后登录2019-10-19
  • 发帖数1916
  • 经验1130枚
  • 威望1点
  • 贡献值232点
  • 好评度161点
1楼#
发布于:2017-11-16 19:26
temp0.value → "123456789123456789"(字符串)
temp0.valueAsNumber → 123456789123456780(数值)
发现了吗?
value 还是正确的
问题发生在从字符串转到数值的时候

根本原因在于 javascript 的 Number 是双精度 64 位浮点数
参考
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number
就是超过了 Number.MAX_SAFE_INTEGER 导致精度丢失

其他浏览器应该也一样
这是由 ECMAScript 标准决定的
新垣结衣
小狐狸
小狐狸
  • UID55997
  • 注册日期2017-09-25
  • 最后登录2019-10-16
  • 发帖数87
  • 经验98枚
  • 威望0点
  • 贡献值60点
  • 好评度8点
  • 忠实会员
  • 社区居民
2楼#
发布于:2017-11-16 19:55
aaaa007cn:temp0.value → "123456789123456789"(字符串)
temp0.valueAsNumber → 123456789123456780(数值)
发现了吗?
value 还是正确的
问题发生在从字符串转到数值的时候
...
回到原帖
可是其它浏览器显示的是 123456789123456789 。。包括 EDGE、IE等一众浏览器。
taoww
狐狸大王
狐狸大王
  • UID39284
  • 注册日期2013-03-18
  • 最后登录2019-10-13
  • 发帖数456
  • 经验413枚
  • 威望0点
  • 贡献值98点
  • 好评度71点
3楼#
发布于:2017-11-16 20:05
很简单。数值是按IEEE-754里规定的binary64这种64位浮点数存储的。能连续精确表示的整数只到2^53=90071992547409922。超过这个上限后,都会按一定规则进行舍入。
反正用这个规范存储数值的软件都会有这个问题,你到google上搜123456789123457000,会看到其他一些相关软件的讨论
新垣结衣
小狐狸
小狐狸
  • UID55997
  • 注册日期2017-09-25
  • 最后登录2019-10-16
  • 发帖数87
  • 经验98枚
  • 威望0点
  • 贡献值60点
  • 好评度8点
  • 忠实会员
  • 社区居民
4楼#
发布于:2017-11-16 20:11
taoww:很简单。数值是按IEEE-754里规定的binary64这种64位浮点数存储的。能连续精确表示的整数只到2^53=90071992547409922。超过这个上限后,都会按一定规则进行舍入。
反正用这个规范存储数值的软件都会有这个问题,你到...
回到原帖
所以其它浏览器是作了特殊处理是吗?因为我用了其它浏览器发现是没有舍入。
taoww
狐狸大王
狐狸大王
  • UID39284
  • 注册日期2013-03-18
  • 最后登录2019-10-13
  • 发帖数456
  • 经验413枚
  • 威望0点
  • 贡献值98点
  • 好评度71点
5楼#
发布于:2017-11-16 20:48
https://html.spec.whatwg.org/multipage/input.html#number-state-(type=number)

“If the element is mutable, the user agent should allow the user to change the number represented by its value, as obtained from applying the rules for parsing floating-point number values to it.”

那个rules for parsing floating-point number values的最后是要求要做舍入的
新垣结衣
小狐狸
小狐狸
  • UID55997
  • 注册日期2017-09-25
  • 最后登录2019-10-16
  • 发帖数87
  • 经验98枚
  • 威望0点
  • 贡献值60点
  • 好评度8点
  • 忠实会员
  • 社区居民
6楼#
发布于:2017-11-16 21:17
非常感谢大家的回答!
新垣结衣
小狐狸
小狐狸
  • UID55997
  • 注册日期2017-09-25
  • 最后登录2019-10-16
  • 发帖数87
  • 经验98枚
  • 威望0点
  • 贡献值60点
  • 好评度8点
  • 忠实会员
  • 社区居民
7楼#
发布于:2017-11-16 21:17
taoww:https://html.spec.whatwg.org/multipage/input.html#number-state-(type=number)

“If the element is mutable, the user age...
回到原帖
非常感谢您的回答,受益匪浅。
aaaa007cn
千年狐狸
千年狐狸
  • UID23968
  • 注册日期2008-05-03
  • 最后登录2019-10-19
  • 发帖数1916
  • 经验1130枚
  • 威望1点
  • 贡献值232点
  • 好评度161点
8楼#
发布于:2017-11-16 22:33
新垣结衣:可是其它浏览器显示的是 123456789123456789 。。包括 EDGE、IE等一众浏览器。回到原帖
我错了
之前看岔了
把 123456789123456780 看成 123456789123457000 了

我觉得 firefox 这个应该是 bug
aaaa007cn
千年狐狸
千年狐狸
  • UID23968
  • 注册日期2008-05-03
  • 最后登录2019-10-19
  • 发帖数1916
  • 经验1130枚
  • 威望1点
  • 贡献值232点
  • 好评度161点
9楼#
发布于:2017-11-16 22:41
taoww:https://html.spec.whatwg.org/multipage/input.html#number-state-(type=number)

“If the element is mutable, the user age...
回到原帖
https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values
Let rounded-value be the number in S that is closest to value, selecting the number with an even significand if there are two equally close values.

Number.parseFloat('123456789123456789') 结果为 123456789123456780
123456789123456780 比 123456789123457000 更接近 123456789123456789
那么理应显示 123456789123456780 而非 123456789123457000

写了个测试页面
通过上下键调整 input type=number 元素的值时
value 会正确的加一减一
valueAsNumber 也会显示对应的数值
唯独 input 输入框的值显示异常
我觉得是 bug
aaaa007cn
千年狐狸
千年狐狸
  • UID23968
  • 注册日期2008-05-03
  • 最后登录2019-10-19
  • 发帖数1916
  • 经验1130枚
  • 威望1点
  • 贡献值232点
  • 好评度161点
10楼#
发布于:2017-11-17 11:56
补上测试用页面

进一步测试后发现输入框的值与 Number.prototype.toLocaleString() 的值类似
都会缩水到 15 位有效数字(即使设置 maximumSignificantDigits 为 21)
设置 toLocaleString 的参数为 undefined, {useGrouping: false} 可以得到完全相同的结果

看来 firefox 不是直接显示原本就是字符串的 value
而会先转成浮点数(valusAsNumber)然后再通过类似 toLocaleString 的方法转回字符串

总之根本原因还是浮点数的精度有限
如何显示、默认取几位有效数字要看标准有没有规定并且浏览器又是如何实现的

firefox 目前这样肯定不妥
附件名称/大小 下载次数 最后更新
input_type_number_test.zip (1KB)  0 2017-11-17 11:54
游客

返回顶部