可能是深夜,但我无法理解这段代码的行为:
public class DT {
static void theTest(double d){
double e = Math.floor(d/1630)*1630;
System.out.println(e-d);
}
public static void main(String[] args) {
theTest(2*1630);
theTest(2*1631);
theTest(2*1629);
theTest(8.989779443802325E18);
}
在我的理解中,所有 4 种情况都应该是非阳性的,即“e”总是<=“d”, 但我确实得到了以下输出:
0.0
-2.0
-1628.0
1024.0
为什么??。 因为这与 FastMath 相同,我怀疑某些双重特定的东西?但是谁能给我解释一下?
最佳答案
当你得到很大的数字时, double 比整数的间距更宽。当您在此范围内进行除法时,结果可以向上或向下舍入。因此,在您的第四个测试用例中,除法 d/1630
的结果实际上四舍五入到最接近的可用 double 值。因为这是一个整数,所以调用 floor
不会改变它。将它乘以 1630
得到的结果大于 d
。
编辑
此效果在 2^52 时开始。一旦超过 2^52,就不再有非整数 double 。在 2^52 和 2^53 之间, double 只是整数。在 2^53 以上, double 比整数间距更宽。
题中除法的结果是5515202112762162.576...
,介于2^52和2^53之间。它四舍五入到最接近的 double ,与最接近的整数相同,即 5515202112762163。现在,floor
不会更改此数字,并且乘以 1630
给出大于 d
的结果。
总而言之,我猜答案的第一句话有点误导 - 您不需要 double 的间距比整数更宽以产生这种效果;您只需要它们的间距至少与整数一样。
d
的值在 0 到 2^52 * 1630 之间,问题中的程序永远不会输出正数。
关于java - 四舍五入的双重陌生感,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24599498/