Превращает ли точность во время отливки int в Java?

Я прочитал это - почему числа с плавающей точкой неточны?

Таким образом, иногда точность может быть изменена числом с плавающей запятой из-за ее стиля представления (научная нотация с показателем и мантисса).

Но если я добавлю целочисленное значение в double, есть ли шанс немного изменить точность двойного в Java?

Я имею в виду,

    int i = 3;
    double d = (double) i;

    System.out.println(d);

на выходе я получил 3.0 как я и ожидал.

но, есть ли вероятность того, что точность изменилась, как 3.000001 из-за стиля представления double в Java?

Ответ 1

Не для int double, но вы можете долго удваивать (или int плавать):

  • Не все 2^53-1 (или меньше -2^53) могут быть представлены в точности двойным;
  • Не все ints больше 2^24-1 (или меньше -2^24) могут быть представлены точно поплавком.

Это ограничение возникает из-за количества бит, используемых для представления мантиссы (53 в парном разряде, 24 в поплавках).

Ответ 2

Вы можете перебирать i до тех пор, пока не найдете 2**i double, который равен 2**i + 1:

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.");
    }
}

Он выводит:

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

Что подтверждает принятый ответ.

Обратите внимание, что в Javascript нет целочисленного типа, и вместо него используются удвоения (они называются Number s). Если они достаточно большие, последовательный Number может быть равен друг другу.