如何最快最好地判断一个字符串数字是否可以准确表示为浮点数(或双精度浮点数)?

9
我正在尝试确定一个表示十进制数的字符串是否可以精确地表示为double。我特别希望有一个JavaScript解决方案,但任何方法都可以(我可以移植代码)。
我可以使用 parseFloat ,转换成字符串,然后看看该字符串是否与输入字符串匹配,但我想知道是否有更好/更快的方法来实现这一点。我想象中具有IEEE浮点标准深入了解的人会有更好的方法来解决这个问题,但那个人不是我。

parseFloat("Infinity") = "Infinity" 的意思是将字符串"Infinity"转换为浮点数。 - soft87
@T.J.Crowder 我并不是说我所描述的方法不能“运行”,我只是希望有一种更符合IEEE规范的方法。我所描述的方法相当粗暴。 - B T
@soft87 不是的... parseFloat("Infinity") === Infinity。但如果你的意思是我的方法在那种情况下不起作用,那么说得好,但这与我的问题并不相关,因为我询问的是表示为字符串的十进制数,而不是JavaScript认为是数字的东西。 - B T
const isFloat = n => !!(n%1) - soft87
1
@BT:嗯,你必须小心。0.1不能完全表示,但是 parseFloat("0.1").toString() == "0.1"是正确的。因为如我在上面的评论中所提到的那样,如果要将IEEE 754二进制浮点数输出为字符串,则标准规则是仅输出足以可靠区分其与相邻可表示值的位数。 - T.J. Crowder
显示剩余3条评论
1个回答

5
任何具有非以数字“5”结尾的小数部分的数字都不能被精确表示为二进制浮点数。可表示的数字具有分数部分,该分数部分是1/(2^N)的和。任何这样的和都以数字“5”结尾。这并不意味着以数字“5”结尾的数字总是可表示的,我们需要进一步检查分数部分是否确实是这样的和。

如果打印出1.1,那么就存在一些舍入。 1.1并不能被完全表示。 - alain
啊,有趣。我很惊讶它默认进行四舍五入。当然,这其中还有更多的内容。我相信在双精度浮点数的最大值以下,仍然存在无法准确表示的大数字,同样地,在最小值的低端也是如此。我希望能够得到一个更通用的解决方案。 - B T
我也会尝试解析-打印-比较的方法,如果您可以禁用舍入,我认为这应该是可能的。但不幸的是,我不懂JavaScript。 - alain
我认为任何不以.5结尾的数字都可以,例如 1.5 是可以的,但是 1.05 不行。 - Keith
1
@Keith 我刚刚编辑了答案,使其更加精确 - 是的,0.05是不可表示的,但例如1/8 + 1/16 = 0.1875是可以表示的。 - alain
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接