Java中的数字规范

Java中的数字规范,java,double,java-8,Java,Double,Java 8,假设在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理想情况下,您应该指定一个数字系统,而不是模糊的“数学”

假设在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双精度算法兼容,适用于操作数为零的除法

第一种情况可能发生:

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语言规范。将一对不为零的有限数除以的过程等价于将精确商映射到双值集或双扩展指数值集


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

然后还有NAN,它永远不等于任何双精度(包括它本身?),以及+0和-0,它们是==但排序为>和<不同。另外,在任何语言中,浮点运算都是不关联的。@markspace,我知道你在说什么,并且我已经进行了编辑,因此在数学上假设它是
+0==-0
,请提供
int
input
x1,y1,x2,y2
表示矛盾。如果它们是
long
值,肯定会发生这种情况,但我不确定是否有一种情况适用于
int
s。因为
double
的精度是已知的,所以使用接近精度极限的值来构造这种情况应该很容易。然而,我不清楚我们为什么要为你做这项工作。“你尝试了什么?”霍尔格我回答了这个问题,因为对于我来说,为第一个命题找到一个例子,并为第二个命题找到一个不存在任何例子的论点似乎并不那么微不足道。很好的解释!也可使用+1作为除法运算符参考。