int和double除以double java
我如何解释以下内容:int和double除以double java,java,double,ieee-754,Java,Double,Ieee 754,我如何解释以下内容: double o = 2.3; int i = (int) (o * 100000.0); double d = i / 100000.0; System.out.println(d); 印刷品2.29999 double o = 2.3; double i = o * 100000.0; double d = i / 100000.0; System.out.println(d); 印刷品2.3 当一个i
double o = 2.3;
int i = (int) (o * 100000.0);
double d = i / 100000.0;
System.out.println(d);
印刷品2.29999
double o = 2.3;
double i = o * 100000.0;
double d = i / 100000.0;
System.out.println(d);
印刷品2.3
当一个int除以double时,java不是先将int转换为double,然后再进行除法吗?如果是这样,两个代码块应该有效地打印相同的值
我似乎缺少一些IEEE 754浮点精度规范和/或内联的jvm优化
double i = 2.3 * 100000.0;
double d = i / 100000.0;
作为
双d=2.3*100000.0/100000.0;
有效地取消了分区并使其成为不可操作的
想法
我似乎缺少一些IEEE 754浮点精度规范
使用int时,它会截断小数部分,无论它与下一个整数值有多接近。它是不可逆的,因为信息丢失了,所以您不会得到相同的结果也就不足为奇了
你可以做的是以下几点
double o = 2.3;
long l = Math.round(o * 100000.0);
double d = l / 100000.0;
System.out.println(d);
内联的jvm优化。。。让这成为一个禁区
JVM可能会对其进行优化,但不会改变结果。如果优化改变了结果,则是优化程序中的错误
double i = o * 100000.0;
之后i的值是2299999.999999997通过添加一个简单的打印语句,您可以自己看到这一点;这是由于
在此之后的i值为2299999,即上面的值,由于int转换,小数部分被截断
因此,
double d = i / 100000.0;
在两个代码段中使用两个数值不同的i值,即它们相差约1,因此输出不同
您的说法是正确的,在将int除以double时,int首先转换为double,这是通过字节码指令i2d完成的。2.3在IEEE-754 64位二进制浮点中不完全可表示。在第一个代码序列中发生的是: 将源文本2.3转换为最接近的可表示值2.2999999999822364316059974953221893310546875。 将其乘以100000的精确数学结果也无法精确表示,因此将其四舍五入为2299999.9999999970896169543266229638671875。 将其转换为int时,转换将截断,生成229999。 再除以100000轮,产生2.299900000000020094148567295633256435394287109375。 打印上述内容时,Java将其显示为“2.29999”。
这就是已知的二进制操作级别问题。这就是为什么在比较某些双精度值时,不能使用==,而要使用具有精度的特殊比较方法setting@ElliotTereschuk:问题中没有==运算,“二进制运算级别”不是浮点运算中常用的术语。@EricPostDischil Simple check with==显然在2.29999==2.3时返回false,这是非常常见的错误。这个评论更像是建议使用舍入和@ElliotTereschuk:问题并不是问为什么比较会返回意外的结果;它问为什么两个结果不同。关于比较的评论与此问题无关。当我用0.1替换2.3时,为什么没有这个问题?0.1不能用双精度表示。@fou x86:有时最近的可表示值低于原始值,有时更高。在2.3的情况下,该值较低。如果是.1,则更高,为0.10000000000000055115123125782702118158340451015625。由于四舍五入,乘以100000正好得到10000。将其转换为整数将产生10000。除以100000将生成0.100000000000000551151231257827021181583404540105625,显示为“.1”。了解Java的默认浮点值显示仅显示足够的数字以区分该值与任何相邻值可能会有所帮助。因此,它为0.1000000000000005555115123125782702118158340454015625生成“.1”,因为将“.1”转换回浮点会生成原始值。如果打印的值稍大或稍小,Java将使用更多的数字来区分它。因此,默认情况下,Java在显示浮点值时会有一点“撒谎”。到目前为止,我找到的获得双d精确打印的最简单方法是System.out.printlnnew BigDecimald。我很惊讶没有人链接到Goldberg的论文,每个计算机科学家都应该知道浮点算术。[pdf]
double d = i / 100000.0;