假设在jdk 8规范中,x1, x2
和y1,y2
是int
变量,我想知道以下情况是否可以发生:
mathematically x1/y1 != x2/y2 but in Java x1/(double)y1 == x2/(double)y2
mathematically x1/y1 == x2/y2 but in Java x1/(double)y1 != x2/(double)y2
数学上假设 0/0 != 0/0
和 Inf == Inf
和 +0 == -0
最佳答案
理想情况下,您应该指定一个数字系统,而不是模糊的“数学上”。数学中有很多定义除法的系统。我本以为你的意思是实数算术,但它有一个零,而且你似乎允许除以零,而实数算术没有定义。我假设您指的是不涉及零的除法的实数算术,以与具有零操作数的除法的 Java double 算术兼容的方式扩展。
第一种情况可能发生:
x1 = Integer.MAX_VALUE
y1 = Integer.MAX_VALUE-1
x2 = Integer.MAX_VALUE-1
y2 = Integer.MAX_VALUE-2
两个双除法得到相同的答案:1.0000000004656613
显然,两个部门有不同的确切答案。小数点后 40 位 BigDecimal 结果为:
1.0000000004656612877414201272105985574523
1.0000000004656612879582605622125704244886
这是一个演示程序:
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
double baseDouble = Integer.MAX_VALUE;
double minus1Double = Integer.MAX_VALUE - 1;
double minus2Double = Integer.MAX_VALUE - 2;
BigDecimal baseBD = new BigDecimal(Integer.MAX_VALUE);
BigDecimal minus1BD = new BigDecimal(Integer.MAX_VALUE - 1);
BigDecimal minus2BD = new BigDecimal(Integer.MAX_VALUE - 2);
System.out.println("base " + baseDouble + " " + baseBD);
System.out.println("minus1 " + minus1Double + " " + minus1BD);
System.out.println("minus2 " + minus2Double + " " + minus2BD);
System.out.println("Double base/minus1 " + baseDouble / minus1Double);
System.out.println("Double minus1/minus2 " + minus1Double / minus2Double);
System.out.println("BigDecimal base/minus1 "
+ baseBD.divide(minus1BD, 40, BigDecimal.ROUND_HALF_EVEN));
System.out.println("BigDecimal minus1/minus2 "
+ minus1BD.divide(minus2BD, 40, BigDecimal.ROUND_HALF_EVEN));
}
}
输出为:
base 2.147483647E9 2147483647
minus1 2.147483646E9 2147483646
minus2 2.147483645E9 2147483645
Double base/minus1 1.0000000004656613
Double minus1/minus2 1.0000000004656613
BigDecimal base/minus1 1.0000000004656612877414201272105985574523
BigDecimal minus1/minus2 1.0000000004656612879582605622125704244886
很容易看出,对于没有零操作数的除法来说,第二种情况是不可能的。
每个 int
都可以精确地转换为 double,因此 double 的精确商与原始值的精确商相匹配。有关除法的定义,请参阅 Java 语言规范 15.17.2 Division Operator / 。将一对都不为零的有限数相除的过程相当于将精确商映射到 double 值集或 double 扩展指数值集。
对于 int
范围来说,double
中的指数上溢和下溢是不可能的,因此两个值集将给出相同的答案。舍入规则与导致结果舍入的计算无关,因此具有相同精确商的 int 值 double 的两个除法具有相同的舍入结果。
关于java - Java 中的数值规范,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26576614/