Gar*_*son 16 java floating-point double
我是一位经验丰富的开发人员,但不是数学专家。我对IEEE浮点规范了解得足够多,因此害怕做出关于解析,打印和比较它们的假设。
我知道我可以double从Stringusing中解析一个Double.parseDouble(String s)。我知道我还可以分析相同的字符串转换成BigDecimal使用new BigDecimal(String s),然后要求BigDecimal的double使用BigDecimal.doubleValue()。
我浏览了这两种技术的API和代码,似乎BigDecimal有很多不同的解析和转换选项。
如果所有的字符串输入都不在正负范围之内,是否保证两种技术(Double.parseDouble(s)和new BigDecimal(s).doubleValue())都能产生完全相同的double原始值Double.MAX_DOUBLE?
对于大多数输入值,两种技术应产生相同的值。虽然他们仍然有可能不会,但看起来不太可能。
\n构造函数BigDecimal(String)Javadocs指出:
\n\nAPI注意事项:
\n\n
float对于和NaN 和 \xc2\xb1Infinity以外的值,此构造函数与和double返回的值兼容。Float.toString(float)Double.toString(double)
然而,该Double.parseDouble(String)方法指出:
\n\n返回一个新
\ndouble值,该值被初始化为指定的值,由类的方法String执行。valueOfDouble
接下来描述该方法接受的格式。
\n让我们测试一下!
\n让我们测试一些值。彻底测试这一点看起来需要付出巨大的努力,但让我们测试一下,包括一些字符串值,这些值表示已知会产生浮点错误或不精确表示的值。
\npublic static void main(String[] args)\n{\n String[] values = {"0", "0.1", "0.33333333333333333333", "-0", "-3.14159265", "10.1e100",\n "0.00000000000000000000000000000000000000000000000000142857142857",\n "10000000000.000000000000000001", "2.718281828459",\n "-1.23456789e-123", "9.87654321e+71", "66666666.66666667",\n "1.7976931348623157E308", "2.2250738585072014E-308", "4.9E-324",\n "3.4028234663852886E38", "1.1754943508222875E-38", "1.401298464324817E-45",\n String.valueOf(Math.E), String.valueOf(Math.PI), String.valueOf(Math.sqrt(2))\n };\n for (String value : values) {\n System.out.println(isDoubleEqual(value));\n }\n}\n// Test if the representations yield the same exact double value.\npublic static boolean isDoubleEqual(String s) {\n double d1 = Double.parseDouble(s);\n double d2 = new BigDecimal(s).doubleValue();\n return d1 == d2;\n}\nRun Code Online (Sandbox Code Playgroud)\n对于这些值,我得到了所有trues。这绝不是详尽无遗的,因此很难证明它对于所有可能的double值都是正确的。只需要举出一个false反例即可。然而,这似乎是一些证据,表明它对于所有合法的double字符串表示都是正确的。
我还尝试过前导空格,例如" 4". 构造BigDecimal(String)函数抛出了 aNumberFormatException但Double.parseDouble正确地修剪了输入。
构造函数BigDecimal(String)不会接受Infinityor NaN,但您只询问正常的有限范围。该Double.parseDouble方法接受十六进制浮点表示,但BigDecimal(String)不接受。
如果包含这些边缘情况,一种方法可能会引发异常,而另一种方法不会引发异常。如果您正在寻找范围内有限值的普通以 10 为基数的字符串,答案是“看起来有可能”。
\n对于所有字符串输入,这两种技术(
Double.parseDouble(s)和new BigDecimal(s).doubleValue())是否保证生成完全相同的双精度原始值(前提是该值不超出 plus 或 minus 的范围)Double.MAX_DOUBLE?
不,当然不是。
一方面,有一些字符串输入Double.parseDouble(s)支持但new BigDecimal(s)不支持(例如,十六进制文字)。
另一方面,Double.parseDouble("-0")产生负零,而new BigDecimal("-0").doubleValue()产生正零(因为BigDecimal没有带符号零的概念)。
虽然与你的问题没有直接关系,但为了其他读者的利益,我被要求指出Double.parseDouble(s)支持 NaN 和无穷大,而不支持 NaN 和无穷BigDecimal大。
| 归档时间: |
|
| 查看次数: |
145 次 |
| 最近记录: |