При переводе числа int во float и обратно теряется точность числа

Рейтинг: 12Ответов: 0Опубликовано: 03.03.2023

Вопрос на злобу дня освежить знания о числе с плавающей точкой и потренировать перевод этого числа в двоичную систему и обратно.

В документах оракла в пункте 5.1.2 приводится пример с потерей данных числа при переводе его в тип float, а затем обратно в int.

class Test {
public static void main(String[] args) {
        int big = 1234567890;
        float approx = big;
        System.out.println(big - (int)approx); //output -46
    }
}

Вопрос - почему именно -46?

Я вручную перевёл число 1234567890 в двоичный вид числа с плавающей точкой. Получилось следующее: 1-ый бит на хранение знака (0), следующие 8 битов на хранение экспоненты, оставшиеся 23 бита на хранение мантиссы. Приступим:

Число 1234567890 в двоичной системе будет 1001001100101100000001011010010. Далее необходимо записать это число в экспонентной форме (т.е. перенести запятую на столько разрядов, чтобы перед ней была только 1 единица). Делаем: 1,001001100101100000001011010010

Мы перенесли запятую 30 раз влево, соответственно наша экспонента будет 30 (+127) = 157.

157 в двоичной системе будет 10011101.

Соответственно наше число в экспонентной форме записи примет такой вид:

Знак / экспонента / мантисса

0 / 10011101 / 00100110010110000000101

Про знак и экспоненту всё понятно, а вот с мантиссой поступают так: отбрасывают первую единицу и пишут оставшиеся 23 числа (т.к. свободно всего 23 бита). Оставшиеся биты, а именно 1010010 просто отбрасываются.

Соответственно при переводе этого числа обратно в десятичную систему нам как раз и не будет хватать этих 7 бит (1010010).

Т.е. наше число примет следующий вид в двоичной системе:

100100110010110000000101 (0000000) - добиваем оставшиеся "потерянные 7 битов" нулями.

Данное число представляет собой в десятичной системе 1234567808 (что на 82 меньше исходного).

Так почему же на выходе в консоли при вычитании чисел мы получаем разницу 46?

Ответы

Ответов пока нет.