Двойной к Int без потери точности - PullRequest
0 голосов
/ 09 сентября 2018

Следующее объявление дает мне ошибку во время компиляции "Ошибка: (19, 13) Java: несовместимые типы: возможное преобразование с потерями из double в int"

int i1 = 10.0;

// Error:(19, 14) java: incompatible types: possible lossy conversion from double to int

Вопрос 1

Я понимаю ошибку, но может ли компилятор не сделать вывод - в данном конкретном случае - что не будет потери точности?

Вопрос 2

Если я явно преобразую двойное число в int, то оно прекрасно скомпилируется (даже не предупреждение), хотя я определенно теряю точность в этом примере

int i2 = (int)9999999999999.999999999;

Если я не могу скомпилировать первый случай - без потерь - тогда почему этот второй пример с явным преобразованием даже не генерирует предупреждение компилятора?

Ответы [ 4 ]

0 голосов
/ 09 сентября 2018

Присвоение значения double переменной int потребует сужающего преобразования , даже если значение является константой времени компиляции, и, следовательно, требует an явное приведение.

За исключением , постоянное значение int (или short или char) может быть присвоено переменной byte, short или char без приведения, если константа фактически вписывается в диапазон значений переменных, как явно задокументировано в Спецификации языка Java, раздел 5.2. Контексты назначения :

Контексты присваивания позволяют присваивать переменной значение ( §15.26 ); тип выражения должен быть преобразован в тип переменной.

Контексты присваивания позволяют использовать одно из следующего:

  • преобразование личности ( §5.1.1 )

  • расширяющееся примитивное преобразование ( §5.1.2 )

  • расширение эталонного преобразования ( §5.1.5 )

  • преобразование бокса ( §5.1.7 ), за которым может последовать расширение эталонного преобразования

  • преобразование распаковки ( §5.1.8 ), необязательно с последующим расширением примитивного преобразования.

Если после применения перечисленных выше преобразований результирующий тип является необработанным типом ( §4.8 ), тогда может быть выполнено непроверенное преобразование ( §5.1.9 ) приложенное.

Кроме того, , если выражение является константным выражением ( §15.28 ) типа byte, short, char или int:

  • Может использоваться сужающее примитивное преобразование, если тип переменной равен byte, short или char, а значение константного выражения представлено в типе переменной переменная .

  • Может использоваться сужающее примитивное преобразование с последующим преобразованием в бокс, если тип переменной:

    • Byte и значение константного выражения представляется в виде byte.

    • Short и значение константного выражения представимо в виде short.

    • Character и значение константного выражения представляется в виде char.

0 голосов
/ 09 сентября 2018

Ответ на вопрос 1

По компилятору происходит потеря точности, потому что компилятор видит только, что у вас есть переменная int слева и двойное значение справа. Компилятор не настолько умен, чтобы понять, что 10.0 не потеряет точность при преобразовании в int.

Теоретически компилятор может быть скомпилирован так, чтобы компилировать это утверждение, но в этом нет реальной выгоды. Почти никто не пишет int x = 10.0.

Ответ на вопрос 2

Действительно, потеря точности есть, но почему компилятор не жаловался? Потому что вы использовали актерский состав. Вы написали (int). Это вы показываете компилятору, что знаете, что делаете. Написав актерский состав, вы сообщаете ему, что знаете о возможной потере точности.

0 голосов
/ 09 сентября 2018

Интересный вопрос

Теоретически это возможно, ну javac не жалуется при выполнении:

short s = 12;

Даже если 12 - это постоянная времени компиляции типа int, поэтому она может сделать вывод, что точность не потеряна. Я думаю, это то, что команда компиляторов посчитала наиболее подходящей.

Хорошо, когда вы cast - это другая история, это все равно, что сказать "верь мне, я знаю, что я делаю", даже если ты теряешь точность.

0 голосов
/ 09 сентября 2018

Теоретически, компилятор может сделать вывод, что конкретный пример в # 1 на самом деле не потеряет точность, основанную на значении литерала, но, как вы видели, это не так.

Явное приведение указывает компилятору, что вам известно о ситуации, и обрабатывает его, поэтому код фактически компилируется. Однако большинство IDE могут быть настроены на выдачу предупреждения и в такой ситуации.

...