【问题标题】:Does "System.out.println( DECIMAL )" always output the same DECIMAL in the code?“System.out.println(DECIMAL)”是否总是在代码中输出相同的 DECIMAL?
【发布时间】:2014-03-04 11:24:42
【问题描述】:

当然, System.out.println( 0.1 ); 输出0.1。但是对于任意小数来说总是如此吗? (排除双精度本身导致的情况。如System.out.println( 0.10000000000000000001);输出0.1

当我点击System.out.println( DECIMAL ); 时,我认为 DECIMAL 被转换为二进制(双精度)并且该二进制被转换为十进制(以字符串形式输出十进制)


考虑以下转换。

十进制[D1] -> (CONVERSION1) -> 二进制[B] -> (CONVERSION2) -> 十进制[D2]

CONVERSION1

(在double有效位范围内)选择[D1]最接近的二进制为[B]

例如[D1] 0.1 -> [B] 0x0.1999999999999a

CONVERSION2

[D2]是能唯一区分[B]且位数最小的十进制数。

例如[B] 0x0.1999999999999a -> [D2] 0.1

引用Java7 API Double.toString(double d)

m 或 a 的小数部分必须打印多少位?必须至少有一个数字来表示小数部分,除此之外,必须有尽可能多的数字,但仅能将参数值与相邻的 double 类型值区分开来。也就是说,假设 x 是由该方法为有限非零参数 d 生成的十进制表示所表示的精确数学值。那么 d 必须是最接近 x 的 double 值;或者如果两个 double 值同样接近 x,则 d 必须是其中之一,并且 d 的有效位的最低有效位必须为 0。


我的问题

“[D1]=[D2]”总是正确的吗?


我为什么要问这个问题

考虑下面的案例,

将用户的十进制输入保存为双精度 -> 显示该十进制

我想知道 [user's input = display ] 是否有保证。

(如上所述,排除由双精度数本身导致的情况。因为这种长输入很少见。)

我知道当我需要精确算术时,我应该使用 BigDecimal。但在这种情况下,我不需要精确的算术。只想显示与用户输入相同的小数。

【问题讨论】:

  • 听起来你很了解,但你想要自己的方式!! :) 但看到一些答案会很有趣。
  • 你的问题我看了两遍,还是没看懂你的问题。

标签: java floating-point floating-point-precision


【解决方案1】:

这部分取决于您对平等的定义。如果您需要精确的字符串匹配,答案是否定的。例如:

System.out.println(0.1e-1);

打印

0.01

现在假设“相等”表示十进制值相等,因此0.1e-10.01 相等。

如果您将双精度数限制为少于 16 位有效十进制数字的正常数字(不是次正规数、上溢或下溢),那么您是安全的。无数个十进制小数四舍五入到每个可以用双精度精确表示的二进制小数。要恢复原件,它必须是该集合中最短的成员。这意味着它与两个最接近的相同或更短长度的十进制数之间的差异必须足够大,以确保它们四舍五入到不同的双精度数。要获得另一个长度相同或更短的十进制数,需要更改原始数字的至少一个十进制 ulp。

如果两个十进制数在 2^54 中相差不止一个部分,并且在正常数字范围内,则它们相距太远而无法映射到同一个双精度数。

这个推理不适用于次正规数,因为它们的精度低于正规数:

System.out.println(0.123451234512345e-310);

打印

1.2345123451236E-311

即使输入只有 15 个有效数字。

【讨论】:

    【解决方案2】:

    第一次从十进制到二进制的转换可能会产生另一个数学值,因为并非每个十进制都可以精确地表示为二进制数。这与二进制的精度无关,以0.1为例。

    从二进制到十进制的第二次转换始终可以无损方式进行,即产生相同的数学值。这通常需要一个长得离谱的十进制表示,因此在实践中,您会将值四舍五入为更短的表示,这样就不再是相同的数学值。

    您的问题“[D1]=[D2] 总是正确的吗?”的答案因此,一般来说没有。这完全取决于二进制和十进制表示的准确性。

    【讨论】:

    • 有没有输出相同小数的实际案例?
    • @idi_prog 你的意思是特殊情况System.out.println( DECIMAL )?俗话说,我不知道。这需要仔细分析边缘情况。我认为,很少有不同的输出。
    猜你喜欢
    • 1970-01-01
    • 2014-08-18
    • 2015-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-29
    • 1970-01-01
    相关资源
    最近更新 更多