java - Java 中的数值规范

标签 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

最佳答案

理想情况下,您应该指定一个数字系统,而不是模糊的“数学上”。数学中有很多定义除法的系统。我本以为你的意思是实数算术,但它有一个零,而且你似乎允许除以零,而实数算术没有定义。我假设您指的是不涉及零的除法的实数算术,以与具有零操作数的除法的 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/

相关文章:

Java Regex - 使用别名更改路径

c# - 将字符串转换为 double 或 float c#

loops - 使用流迭代 n 次而不是使用 for 循环来创建 n 个项目

c# - LINQ查询,忽略带有某些小数点的结果

c - 为什么在我的程序中从 float 到 double 的隐式转换会返回无意义的数字?

java - 为什么要重写接口(interface)方法?

java - 无法使用高于 1.8 的 Java 的 maven-compiler-plugin 进行编译

java - 在多个类之间共享 Java 中的常量字符串好吗?

java - 支持Android开发的基于云的Java IDE?

java - 如何使用Java验证selenium webdriver中的单词是否为粗体?