Java: почему я не могу объявлять целые типы, используя экспоненциальную запись?

Я могу легко прочитать 2e15 как "два квадриллиона" с первого взгляда, но для 2000000000000000 мне приходится считать нули, что занимает больше времени и может привести к ошибкам.

Почему я не могу объявить int или long, используя литерал, такой как 2e9 или 1.3e6? Я понимаю, что отрицательная степень числа 10, например 2e-3, или степень числа 10, меньшая числа десятичных разрядов, например 1.0003e3, будет давать число с плавающей запятой, но почему Java не разрешает такие объявления, и просто обрезать часть с плавающей запятой и выдать мягкое предупреждение в тех случаях, когда результирующее значение не является целым?

Есть ли техническая причина, по которой это плохая идея, или все дело в безопасности типов? Разве не было бы тривиально для компилятора просто проанализировать оператор вроде

long x = 2e12 as long x = 2000000000000 //OK for long

и int y = 2.1234e3 как int y = 2123.4 //warning: loss of precision


person odougs    schedule 14.07.2013    source источник
comment
Эрик Липперт: меня часто спрашивают почему компилятор не реализует ту или иную функцию, и, конечно же, ответ всегда один и тот же: потому что никто не реализовал ее. Функции начинаются как нереализованные и становятся реализованными только тогда, когда люди прилагают усилия для их реализации. : нет усилия, нет возможности. Это, конечно, неудовлетворительный ответ, потому что обычно человек, задающий вопрос, делает предположение, что функция настолько хороша, что у нас должна быть причина, чтобы не реализовать ее.   -  person John Kugelman    schedule 14.07.2013
comment
@BrianRoach: я знаю, что такое целое число. Я спрашивал, есть ли конкретная причина, почему числа, которые выражены в форме с плавающей запятой, но оцениваются как интегральное значение, например: 2.3e3 == 2300, не могут быть присвоены без явного приведения. Может быть, причина просто в том, что цитировал Джон Кугельман. Это имело бы смысл. Причина, по которой я спросил, заключается в том, что мне было любопытно, есть ли техническая причина, по которой такая функция была бы плохой идеей.   -  person odougs    schedule 14.07.2013
comment
Нет, я понял первую часть... но это не ваш второй пример; int y = 2123.4   -  person Brian Roach    schedule 14.07.2013
comment
@BrianRoach В моем втором примере я предполагал, что компилятор выдаст предупреждение о нецелочисленном выражении с использованием экспоненциальной записи, присваиваемой целому числу, в отличие от первого примера, в котором выражение определяется как целочисленное значение и поэтому может быть присвоен целочисленному типу без потери точности. Я понимаю, что Java не допускает такие присваивания без явного приведения; Мне просто было любопытно, какие дизайнерские решения были задействованы.   -  person odougs    schedule 14.07.2013


Ответы (3)


Это потому, что при использовании научной нотации вы создаете число с плавающей запятой (двойное в вашем примере). И вы не можете присвоить целое число с плавающей запятой (это было бы сужающим примитивным преобразованием, что не является допустимым преобразованием присваивания).

Так что это тоже не сработает, например:

int y = 2d; //can't convert double to int

У вас есть несколько вариантов:

  • явно привести плавающую точку к целому числу: int y = (int) 2e6;
  • с Java 7+ используйте разделитель тысяч: int y = 2_000_000;
person assylias    schedule 14.07.2013
comment
Варианты, которые вы упомянули, просты в использовании и устраняют необходимость в гипотетической функции, о которой я говорил. Спасибо! - person odougs; 15.07.2013
comment
@assylias Да, но число без точки счисления и без суффикса d или f считается int. Поэтому я думаю, что ОП спрашивал, почему, например, 2e8 не будет интерпретироваться как int, и почему 2e12l не будет интерпретировано как long (что согласуется с тем, как интерпретируются ненаучные числа). Таким образом, ответ, кажется, таков. Нет никаких технических причин, по которым разработчики компилятора Java использовали научную нотацию в этом отношении. Они могли бы сделать то, что предлагал ОП, но они этого не сделали - возможно, они просто не подумали сделать это таким образом. - person yroc; 21.06.2016
comment
@yroc ну да - я просто указал на соответствующие части спецификации, в которых говорится, что это не работает. Почему это было сделано именно так, нужно спросить у разработчиков JDK. Смотрите также первый комментарий под вопросом. - person assylias; 21.06.2016

Потому что это недостаток Java.

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

person nmr    schedule 19.02.2014

Вы спрашиваете о правилах записи целочисленных литералов. См. эту ссылку: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html Возможность использовать экспоненциальное представление в качестве целочисленного литерала действительно могла бы упростить задачу, но пока не реализована. Я не вижу никакой технической причины, которая помешала бы реализовать такую ​​функцию.

person Tarik    schedule 14.07.2013