[英]How does conversion from double to int work in Java?
对于以下代码(Java):
double d = (double) m / n; //m and n are integers, n>0
int i = (int) (d * n);
i == m
最后一个表达式总是正确的吗? 如果不是,这总是正确的吗?:
i = (int) Math.round(d * n);
i == m
int i = (int) (d * n); i == m;
对于 m=1,n=49,这是错误的。
i = (int) Math.round(d * n); i == m;
我的直觉告诉我这应该是真的,但可能很难严格证明。
您提出的第二个问题涉及 Java 中的ulp有多大。
如果 ulp 超过1/(n)
,则乘法四舍五入将不会恢复原始除法整数。 通常,较大的 ulp 与较大的双精度值相关联。 与双精度相关的 ulp 在 9E15 左右开始超过 1; 如果您恢复的双打就在那里,那么您可能会发现 round() 没有得到预期答案的问题。 但是,当您使用 int 值时,除法分子的最大值将是Integer.MAX_VALUE
。
以下程序测试n
的所有正 integer 值,以查看在尝试恢复已划分的 int 时哪一个导致舍入误差的最大可能性:
public static void main(String[] args)
{
// start with large number
int m = Integer.MAX_VALUE;
double d = 0;
double largestError = 0;
int bigErrorCause = -1;
for (int n = 1; n < Integer.MAX_VALUE; n++)
{
d = (double) m / n;
double possibleError = Math.ulp(d) * n;
if (possibleError > largestError)
{
largestError = possibleError;
bigErrorCause = n;
}
}
System.out.println("int " + bigErrorCause + " causes at most "
+ largestError + " error");
}
output 是:
int 1073741823 最多导致 4.768371577590358E-7 错误
使用 Math.round 进行舍入,然后转换为 int 应该恢复原始 int。
从数学上讲,它应该是正确的。 但是,您可能会遇到浮点舍入错误,从而使其错误。 您几乎不应该使用==
比较浮点精度数。
你最好使用这样的阈值来比较它们:
Math.abs( d*n - m ) < 0.000001;
注意这两个语句应该是等价的
i = (int) (d * n);
i = (int) Math.round(d * n);
但是,例如,如果d=3/2
和n=2
,浮点错误可能会导致i=2.999999999999
在截断/舍入后为 2。
第一个绝对不总是正确的。 第二个我会说是的,这是真的,但只是因为我想不出一个反例。
如果 n 非常大,它可能是错误的,我不确定。 我知道这至少在 99% 的情况下都是正确的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.