在转换int期间精度是否会稍微改变,以便在Java中加倍?

Does precision change slightly during casting int to double in Java?

我读过这个-为什么浮点数不准确?

因此,有时浮点数的精度会因其表示方式(科学符号,带指数和尾数)而改变。

但是如果我将整数值转换为加倍,有没有机会改变Java中的双精度?

我是说,

1
2
3
4
    int i = 3;
    double d = (double) i;

    System.out.println(d);

我得到了预期的3.0输出。

但是,由于Java中的双重表示方式,是否有可能像EDCOX1×1那样精确地改变?


不适用于int到double,但您可以使用long到double(或int到float):

  • 并非所有大于2^53-1或小于-2^53的多头都能精确地用一个双精度数表示;
  • 不是所有大于2^24-1的整数(或小于-2^24的整数)都能精确地用浮点表示。

这种限制是因为用来表示尾数的位数(双数53位,浮点数24位)。

  • 也可以轻松检查:int i = Integer.MAX_VALUE; float f = (float) i; double d = (double) i;,它将使f != d的值为真,因为float不能正确地表示值。
  • @本这样一个简单的检查可能会产生误导:你可能碰巧选择了Integer.MIN_VALUE来测试这个问题,你会发现Integer.MIN_VALUE可以精确地表示为一个浮点数和一个双精度数。恰好它适用于Integer.MAX_VALUE
  • 没错。可能不是最佳的例子。刚刚发现它值得一提,因为它是一个"快速检查"证明这一点。
  • @本不,这证明不了什么。您还可以显示2^34以这种方式适合浮点,即使它不适合in t。
  • "快速检查"方法可以通过始终测试一个数字及其继承者来恢复。如果测试范围内存在溢出问题,则只能精确表示其中一个问题。要进行更明确的检查,请尝试以下几行:long num = (long) Math.pow(2,53); System.out.println(num == (long) (double) num); System.out.println((num+1) == (long) (double) (num+1)); System.out.println(num == (long) (double) (num+1));
  • 证明"规则"是错误的只需一个例外。仅仅因为Integer.MAX_VALUE的"公正"发生了作用,并不能使它不可靠地证明这个案件。
  • 注:2^24和2^53都是可表示的(浮点和双精度),浮点中的第一个不可表示整数是2^24+1,双精度中的第一个不可表示整数是2^53+1。
  • 还要注意,53和24是尾数的有效大小,实际大小要小一点,因为IEEE浮点不需要存储前导1。
  • @andyturner检查p(x)并不总是检查~p(~x);如果ben的检查失败,则存在无法表示的整数。如果本的支票成功了,它不会告诉你任何有趣的事情。
  • @YakkAdamnevraumont,我没有很好地表达的一点是,如果你不记得这些可代表的范围是什么,测试一个数字可能误导你,如果你只检查一个(或几个)数字。你可能只是运气不好,选一个完全可以代表的数字。
  • 你能做的就是检查奇数,如果一个奇数比所有较小(接近于零)的奇数都可以表示。


您可以迭代i,直到找到一个2**i双精度,等于2**i + 1

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.util.stream.IntStream;

public class PrecisionLoss
{
    public static void main(String[] args) {
        double epsilon = 1;
        Integer maxInt = IntStream.iterate(0, i -> i + 1)
                .filter(i -> Math.pow(2, i) == Math.pow(2, i) + epsilon)
                .findFirst().getAsInt();
        System.out.println("Loss of precision is greater than" + epsilon
                +" for 2**" + maxInt +" when using double.");
    }
}

它输出:

1
Loss of precision is greater than 1.0 for 2**53 when using double.

这证实了接受的答案。

注意,在javascript中,没有整数类型,而是使用了double(它们称为Numbers)。如果它们足够大,则连续的Number可以相等。