Подтвердить что ты не робот

Деление на ноль: Undefined Поведение или реализация Определены в C и/или С++?

Что касается деления на ноль, стандарты говорят:

C99 6.5.5p5 - результатом оператора/является фактор от деления первого операнда на второй; результатом оператора% является остаток. В обеих операциях, если значение второго операнда равно нулю, поведение undefined.

С++ 03 5.6.4. Двоичный/оператор дает частное, а двоичный оператор% дает остаток от деления первого выражения на второе. Если второй операнд/или% равен нулю, поведение undefined.

Если бы мы взяли вышеуказанные абзацы по номинальной стоимости, ответ явно Undefined Поведение для обоих языков. Однако, если мы посмотрим дальше в стандарте C99, мы увидим следующий параграф, который представляется противоречивым (1):

C99 7.12p4 - макрос INFINITY расширяется до постоянного выражения типа float, представляющего положительную или беззначную бесконечность, если доступно;

Есть ли у стандартов какое-то золотое правило, где Undefined Поведение не может быть заменено (потенциально) противоречивым утверждением? Не допуская этого, я не считаю необоснованным сделать вывод о том, что если ваша реализация определяет макрос INFINITY, то деление на ноль определяется как таковое. Однако, если ваша реализация не определяет такой макрос, поведение undefined.

Мне интересно, какой консенсус (если таковой имеется) по этому вопросу для каждого из двух языков. Будет ли ответ изменяться, если мы говорим о целочисленном делении int i = 1 / 0 по сравнению с делением с плавающей запятой float i = 1.0 / 0.0?

Примечание (1) В стандарте С++ 03 рассказывается о библиотеке <cmath>, которая включает макрос INFINITY.

4b9b3361

Ответ 1

Я не вижу противоречия. Деление на ноль undefined, период. Не упоминается "... если INFINITY не определен" в любом месте цитируемого текста.

Отметим, что нигде в математике не определено, что 1/0 = бесконечность. Можно так интерпретировать его, но это личная интерпретация стиля "ярлыка", а не звуковой факт.

Ответ 2

1/0 не бесконечность, только

lim 1/x = ∞ (x -> +0)

Ответ 3

Почему?

Это не имеет смысла математически, это не так, как если бы 1/x определялось как ∞ в математике в целом. Кроме того, вам потребуется, по крайней мере, еще два случая: -1/x и 0/x не могут также равняться ∞.

Смотрите деление на ноль в целом, а раздел о компьютерную арифметику в частности.

Ответ 4

У меня есть только черновик C99. В разделе 7.12/4 говорится:

Макрос

    INFINITY

расширяется до постоянного выражения тип float, представляющий позитивные или беззнаковая бесконечность, если таковая имеется; еще к положительной константе типа floatкоторый переполняется во время перевода.

Обратите внимание, что INFINITY может быть задано в терминах переполнения с плавающей запятой, не обязательно делить на ноль.

Ответ 5

Для макроса INFINITY: существует явное кодирование для представления +/- бесконечности в стандарте IEEE754, то есть, если все биты экспоненты установлены, и все бит фракции очищаются (если бит бит установлен, он представляет NaN)

С моим компилятором (int) INFINITY == -2147483648, поэтому выражение, которое оценивается как int i = 1/0, обязательно приведет к неправильным результатам, если INFINITIY был возвращен

Ответ 6

Это был не самый чистый вопрос, а вопрос C/С++.

  • В соответствии со стандартом IEEE 754, который использует все современные компиляторы C/FPU, мы имеем
    • 3.0/0.0 = INF
    • 0.0/0.0 = NaN
    • -3.0/0.0 = -INF

FPU будет иметь флаг состояния, который вы можете установить для генерации исключения, если это необходимо, но это не норма.

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

http://people.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF

Ответ 7

Нижняя строка, C99 (в соответствии с вашими кавычками) ничего не говорит о INFINITY в контексте "реализации". Во-вторых, то, что вы цитируете, не показывает противоречивого значения "поведение undefined".


[Quoting Wikipedia Undefined Страница поведения] "В C и С++ также используется поведение, определяемое реализацией, где языковой стандарт не определяет поведение, но реализация должна выбрать поведение и должна документировать и наблюдать правила, которые он выбрал".

Точнее, стандарт означает "определенный реализацией" (я думаю, только), когда он использует эти слова в отношении оператора, сделанного с тех пор, как "определенный реализацией" является специфическим атрибутом стандарта. В цитате C99 7.12p4 не упоминалось "определяемое реализацией".

[From C99 std (late draft)] "undefined поведение: поведение при использовании непереносимой или ошибочной программной конструкции или ошибочных данных, для которых настоящий международный стандарт не предъявляет никаких требований"

Заметьте, что для поведения Undefined существует "нет требования"!

[C99..] "поведение, определяемое реализацией: неопределенное поведение, когда каждая реализация документирует, как делается выбор"

[C99..] "неуказанное поведение: использование неопределенного значения или другое поведение, если этот международный стандарт предоставляет две или более возможности и не налагает никаких дополнительных требований, которые выбираются в любом случае"

Документация является требованием для поведения, определяемого реализацией.

Ответ 8

Реализации, которые определяют __STDC_IEC_559__, должны соблюдаться требованиями, приведенными в Приложении F, что, в свою очередь, требует семантики с плавающей запятой, соответствующей IEC 60559. Стандарт не налагает никаких требований на поведение деления с плавающей запятой на ноль которые не определяют __STDC_IEC_559__, но для тех, которые его определяют. В тех случаях, когда IEC 60559 определяет поведение, но C-стандарт не поддерживает, C-код, который определяет __STDC_IEC_559__, должен соответствовать стандарту C, как описано в стандарте IEC.

Как определено стандартом IEC 60559 (или стандартом США IEEE-754) с нулевым нулевым значением, NaN, деление числа с плавающей запятой на положительный нуль или постоянный постоянный нуль дает значение INF с тем же знаком, что и дивиденд, а деление числа с плавающей запятой на отрицательный нуль дает INF с противоположным знаком.