Java中的数字规范

时间:2014-10-26 18:48:29

标签: java double java-8

假设在jdk 8规范中,x1, x2y1, y2int变量,我想知道以下情况是否会发生:

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/0Inf == Inf以及+0 == -0

1 个答案:

答案 0 :(得分:2)

理想情况下,您应该指定一个数字系统,而不是模糊的"数学"。数学中有很多系统可以定义分裂。我会假设你的意思是实数算术,但它有一个零,你似乎允许除零,实数运算没有定义。我将假设你的意思是对于不涉及零的分区的实数运算,以与Java双重算术兼容的方式扩展,对于具有零操作数的分区。

第一种情况可能发生:

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,因此双精度的精确商与原始值的精确商相匹配。有关除法的定义,请参阅Java语言规范15.17.2 Division Operator /。将一对有限数除以零的过程等效于将精确商映射到double值集或double-extended-exponent值集。

double范围内的int中的指数溢出和下溢是不可能的,因此这两个值集将给出相同的答案。舍入规则独立于导致结果舍入的计算,因此具有相同精确商的两个具有相同值的商数的双值除法具有相同的舍入结果。