Java 是不是;System.out.println(十进制)“;是否始终在代码中输出相同的小数?

Java 是不是;System.out.println(十进制)“;是否始终在代码中输出相同的小数?,java,floating-point,floating-point-precision,Java,Floating Point,Floating Point Precision,当然,, System.out.println(0.1) 输出0.1。但对于任意的小数点,它总是正确的吗? (不包括由于双倍数字本身的精度而导致的情况。例如,System.out.println(0.100000000000000001);输出0.1) 当我点击System.out.println(十进制)时我认为,十进制被转换成二进制(双精度),二进制被转换成十进制(以字符串形式输出十进制) 考虑以下转换 十进制[D1]->(转换1)->二进制[B]->(转换2)->十进制[D2] 转换1:

当然,,
System.out.println(0.1)
输出
0.1
。但对于任意的小数点,它总是正确的吗? (不包括由于双倍数字本身的精度而导致的情况。例如,
System.out.println(0.100000000000000001);
输出
0.1

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


考虑以下转换

十进制[D1]->(转换1)->二进制[B]->(转换2)->十进制[D2]

转换1

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

e、 g[D1]0.1->[B]0x0.19999999A

转换2

[D2]是能够唯一区分[B]的十进制数,具有最小的数字

e、 g.[B]0x0.1999999999a->[D2]0.1

引述

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


我的问题

“[D1]=[D2]”是否始终为真


我为什么问这个问题

想想下面这个案例,

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

我想知道[用户输入=显示]是否得到保证

(如上所述,排除因双倍数字本身的精度而导致的情况。因为长输入是罕见的情况。)


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

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

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


因此,您的问题“D1=[D2]是否始终正确?”的答案通常是否定的。这完全取决于二进制和十进制表示法的准确性。

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

System.out.println(0.1e-1);
印刷品

0.01
1.2345123451236E-311
现在假设“相等”表示十进制值相等,因此
0.1e-1
0.01
相等

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

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

此推理不适用于次正常数,因为它们的精度低于正常数:

System.out.println(0.123451234512345e-310);
印刷品

0.01
1.2345123451236E-311

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

听起来你好像知道所有的方法,但你想要自己的方法!!:)但是看到一些答案会很有趣。我已经读了你的问题两遍,但我仍然不理解你的问题。是否有一个实际案例不输出相同的十进制数?@idi_prog你是指特殊案例
System.out.println(decimal)
?说真的,我不知道。这需要仔细分析边缘情况。我认为,不同的输出很少会发生变化。