Деление на ноль: неопределенное поведение или реализация, определенные в C и/или c++?
Что касается деления на ноль, стандарты говорят:
C99 6.5.5p5-результатом оператора / является частное от деления первого операнда на второй; результатом оператора % является остаток. В обеих операциях, если значение второго операнда равно нулю, поведение не определено.
c/" class="blnk">C++03 5.6.4-оператор binary / дает фактор, а оператор binary % дает остаток от деления первого выражение на секунду. Если второй операнд / или % равен нулю, поведение не определено.
Если бы мы приняли вышеуказанные абзацы за чистую монету, ответ был бы очевиден Неопределенное Поведение для обоих языков. Однако, если мы посмотрим дальше в стандарте C99, мы увидим следующий абзац, который кажется противоречивым(1):
C99 7.12p4-бесконечность макроса расширяется до постоянного выражения типа float, представляющего положительная или беззнаковая бесконечность, если таковая имеется;
у стандартов есть какой-то золотое правило где неопределенное поведение не может быть заменено (потенциально) противоречивым утверждением? За исключением этого, я не думаю, что неразумно заключать, что если ваша реализация определяет макрос бесконечности, деление на ноль определяется как таковое. Однако, если ваша реализация делает не определите такой макрос, поведение Не определено.
мне любопытно, каков консенсус (если таковой имеется) по этому вопросу для каждого из двух языков. Изменится ли ответ, если мы говорим о целочисленном делении int i = 1 / 0
против деления с плавающей запятой float i = 1.0 / 0.0
?
Примечание (1) стандарт C++03 говорит о <cmath>
библиотека, которая включает макрос INFINITY.
8 ответов
Я не вижу никакого противоречия. Деление на ноль не определено, точка. Нет никакого упоминания о "... если бесконечность не определена" в любом месте цитируемого текста.
обратите внимание, что нигде в математике определено, что 1 / 0 = бесконечность. Один might интерпретируйте его таким образом, но это личная интерпретация стиля "ярлык", а не звуковой факт.
Почему это?
Это не имеет смысла математически, это не так, как если бы 1/x определяется как ∞ в математике в целом. Кроме того, вам понадобится как минимум еще два случая: -1/x 0 и/x не может также равняться ∞.
посмотреть деление на ноль В общем, и раздел о компьютерная арифметика в частности.
у меня есть только черновик C99. В §7.12 / 4 говорится:
макрос
INFINITY
расширяется до постоянного выражения тип float, представляющий положительный или unsigned infinity, если доступно; else к положительной константе типа
float
это переполняет во время перевода.
отметим, что INFINITY
можно определить в терминах переполнения с плавающей запятой, не обязательно делить на ноль.
для макроса INFINITY: существует явное кодирование для представления + / - infinity в стандарте IEEE754, которое заключается в том, что все биты экспоненты установлены и все биты фракции очищены (если бит фракции установлен, он представляет NaN)
С моим компилятором, (int) INFINITY == -2147483648
, поэтому выражение, которое оценивается как int i = 1/0
определенно приведет к неправильным результатам, если INFINITIY будет возвращен
Это был не математический чистейший вопрос, а вопрос C/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
нижняя строка, C99 (согласно вашим котировкам) ничего не говорит о бесконечности в контексте "определенной реализации". Во-вторых, то, что вы процитировали, не показывает непоследовательного значения "неопределенного поведения".
[цитируя неопределенную страницу поведения Википедии] " В C и C++ также используется поведение, определяемое реализацией, где языковой стандарт не определяет поведение,но реализация должна выбрать поведение и должна документировать и соблюдайте правила, которые он выбрал."
точнее, стандарт означает " реализация-определенная "(я думаю, только), когда он использует эти слова в отношении заявления, сделанного, поскольку" реализация-определенная " является конкретным атрибутом стандарта. Цитата C99 7.12p4 не упомянул "реализацию, определенную".
[из C99 std (поздний черновик)] " неопределенное поведение: поведение при использовании непортируемой или ошибочной конструкции программы или ошибочных данных, для которых это Международный стандарт не предъявляет никаких требований"
обратите внимание, что для неопределенного поведения" нет требования"!
[C99 ..] "поведение, определяемое реализацией: неопределенное поведение, в котором каждая реализация документирует, как сделан выбор"
[C99 ..] "неопределенное поведение: использование неопределенного значения или другого поведения, когда этот международный стандарт предоставляет две или более возможностей и не налагает никаких дополнительных требований, на которые пример"
документация является требованием для реализации определенного поведения.
реализации, которые определяют __STDC_IEC_559__
должны соблюдать требования, приведенные в приложении F, которое, в свою очередь, требует семантики с плавающей запятой в соответствии с МЭК 60559. Стандарт не предъявляет никаких требований к поведению деления с плавающей запятой на ноль для реализаций, которые не определяют __STDC_IEC_559__
, но делает для тех, кто его определяет. В случаях, когда IEC 60559 указывает поведение, но стандарт C не делает, компилятор, который определяет __STDC_IEC_559__
требуется C Стандартная вести себя, как описано в стандарте IEC.
как определено в IEC 60559 (или США стандарт IEEE-754) деление ноля на ноль дает Нана, деление с плавающей запятой положительный ноль или константа ноль дает инф значение с тем же знаком делимого и деление с плавающей точкой число отрицательный нуль дает инф с противоположным знаком.