1/0 является допустимым выражением Java?

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

Тот же аргумент можно сказать для почему вы не хотели бы поиска квада или какого-либо другого более высокого порядка.

37
задан Aziz Shaikh 1 October 2012 в 09:44
поделиться

7 ответов

Является ли 1/0 допустимым выражением Java, которое должно компилироваться в любое время в любом месте?

Да.

Что об этом говорит JLS?

Ничего особенного ... кроме того, что деление на ноль приведет к исключению времени выполнения. Однако JLS признает возможность исключений времени выполнения в следующем определении:

«Выражение константы времени компиляции - это выражение, обозначающее значение примитивного типа или String , которое не завершается внезапно и является составлено с использованием только следующего: ... "

(выделение добавлено.) Таким образом, следующее НЕ будет компилироваться:

switch(i) {
    case 1:
    case 1 + 1: 
    case 1 / 0:  // compilation error.
}

Если это законно, есть ли для этого веская причина?

Хороший вопрос. Я полагаю, что это способ выбросить ArithmeticException , хотя это вряд ли является правдоподобной причиной. Более вероятная причина для указания Java таким образом - избежать ненужной сложности в JLS и компиляторах, чтобы иметь дело с крайним случаем, который редко укусит людей.

Но это все мимоходом. Дело в том, что 1/0 является допустимым кодом Java, и компилятор Java никогда не должен отмечать это как ошибку компиляции. (Было бы разумно, если бы компилятор Java выдал предупреждение при условии, что компилятор отключил его с помощью переключателя.)

32
ответ дан 27 November 2019 в 04:49
поделиться

Java явно требует целочисленного деления на ноль, чтобы вызвать ArithmeticException . Присваивание j не может быть отменено, потому что это нарушит спецификацию.

2
ответ дан 27 November 2019 в 04:49
поделиться

Ну, если вы заглянете в класс Double, то увидите следующее:

/**
 * A constant holding the positive infinity of type
 * <code>double</code>. It is equal to the value returned by
 * <code>Double.longBitsToDouble(0x7ff0000000000000L)</code>.
 */
public static final double POSITIVE_INFINITY = 1.0 / 0.0;

Тот же расчет производится в классе Float, только с плавающей точкой вместо двойки. По сути, 1/0 возвращает очень, очень большое число, большее, чем Double.MAX_VALUE.

Следующий код:

public static void main(String[] args) {
    System.out.println(Double.POSITIVE_INFINITY);
    System.out.println(Double.POSITIVE_INFINITY > Double.MAX_VALUE);
}

Выходные данные:

Infinity
true

Обратите внимание на особый случай вывода Double.POSITIVE_INFINITY. Выводится строка, хотя она рассматривается как двойка.

Чтобы ответить на вопрос, да, это законно в Java, но 1/0 разрешается в "бесконечность" и рассматривается иначе, чем стандартные двойки (или поплавки, или так далее и так далее).

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

2
ответ дан 27 November 2019 в 04:49
поделиться

Зачем отлавливать это во время компиляции, если вам все равно понадобится вариант во время выполнения?

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

Также если бы вы установили любую переменную в 0 и делили на нее, Java пришлось бы отслеживать все возможные значения каждой переменной в каждой точке сценария, чтобы перехватить деление на 0 во время компиляции.

С таким же успехом можно сделать исключение только во время выполнения.

0
ответ дан 27 November 2019 в 04:49
поделиться

Это допустимо с точки зрения компиляции , но при выполнении будет выдано исключение!

причина ... ну, программирование должно обеспечивать гибкость, поэтому все выражения и каждый вводимый вами код являются переменной для компилятора, поэтому в математическом выражении X / Y компилятор не заботится, если значение переменной Y равно ( Y == 0 ) или любое другое число для компилятора, это переменная ... если бы компилятор также должен был смотреть на значения, которые считались бы средой выполнения, не было бы ' т это.

0
ответ дан 27 November 2019 в 04:49
поделиться

Это законно, потому что нигде не указано, что компилятор должен сворачивать константные выражения во время компиляции.

«Умный» компилятор может скомпилировать:

a = 1 + 2

как

a = 3

Но нет ничего, что говорило бы, что компилятор ДОЛЖЕН это делать. В остальном 1/0 является допустимым выражением, так же как:

int a;
int b;

a = a/b;

- допустимым выражением.

В RUNTIME генерируется исключение, но это ошибка времени выполнения по какой-то причине.

0
ответ дан 27 November 2019 в 04:49
поделиться

Я покопался в базе данных ошибок и обнаружил интересную информацию.

Идентификатор ошибки 4178182: JLS не определяет поведение для 1/0 как константное выражение

Следующий код недопустим:

 class X {static final int i = 1/0; }

Значение этой константы времени компиляции не определено, поэтому это должна быть ошибка времени компиляции. Подтверждено Гая Стила около 18 месяцев. назад, что это действительно было предполагаемое поведение.

Константа времени компиляции должна иметь статическое значение (это что делает его константой времени компиляции ;-) Например, значение other константы, значения которых определяются константой, содержащей деление нулем не определены. Это влияет на семантику операторов switch , определенное присвоение и отмена назначения и т. д.

ID ошибки 4089107: javac рассматривает целочисленное деление на (постоянный) ноль как ошибку

 public class zero {
public static void main (String [] args) {
System.out.println (1/0);
 }
}

Выполнение вышеуказанного дает:

 zero.java:3: Арифметическое исключение.
System.out.println (1/0);
 ^
1 ошибка

Идентификатор ошибки 4154563: javac допускает деление на нулевые константные выражения в выражениях case.

Компилятор Java дает сбой при попытке скомпилировать следующий тест. Этот тест также вызывает сбой всех версий компилятора 1.2beta4, но ошибка отсутствует в 12.beta3.Ниже приведен пример и диагностика компилятора:

 public class B {
public static void main (String argv []) {
switch (0) {
case 0/0:
 }
 }
}

Оценка: Компилятор сообщал обо всех попытках деления на константу ноль как об ошибках времени компиляции. Это было исправлено в beta3, чтобы код генерировался для деления на постоянный ноль. К сожалению, эта ошибка появилась. Компилятор должен аккуратно обрабатывать деление на ноль в выражении case.

Заключение

Таким образом, вопрос о том, следует ли компилировать 1/0 , был спорной темой обсуждения, некоторые люди цитировали Гая Стила, утверждающего, что это должна быть ошибка времени компиляции, а другие говоря, что этого не должно быть. Похоже, что в конечном итоге было решено, что это не ошибка времени компиляции и не константа времени компиляции.

20
ответ дан 27 November 2019 в 04:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: