2010-06-09 6 views
18

Что касается деления на ноль, стандарты говорят:Деление на ноль: неопределенное поведение или реализация Определены в C и/или C++?

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

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

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

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

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

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

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

+0

Вот еще одна известная шутка: Если x * 0 = y, то как найти x? – psihodelia

+0

@paxdiablo: как вы отменили y/(xy)? Вы должны получить 1/x, но не x – psihodelia

+0

@psihodelia - я бы сказал, что x * 0 = y, find x будет математическим эквивалентом риторического вопроса. x - это ничего или ничего, и поэтому он не имеет ответа, не требуя ответа одинаково. – pxl

ответ

22

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

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

+0

Согласовано.'1/0;' и подобные выражения никоим образом не связаны с макросом 'INFINITY' (если случайно реализация не решит использовать это для разрешения неопределенного поведения). –

+0

@Matthew: относительно вашего комментария в скобках: мои результаты показывают, что это действительно так, что многие (большинство?) Реализаций решили разрешить это. Не сказать, что делает это поведение, определяемое реализацией, но оно * добавляет к путанице. – SiegeX

+0

Не с GCC и друзьями. Я запустил '#include int div_0_i = 1/0; float div_0_f = 1.0f/0.0f; float my_inf = INFINITY; через GNU cpp и получил 'int div_0_i = 1/0; float div_0_f = 1.0f/0.0f; float my_inf = (__builtin_inff()); 'Поэтому я не вижу связи. –

3

Зачем это было?

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

См. division by zero в целом, а также раздел о computer arithmetic в частности.

+0

Я бы утверждал, что 'y = 1/x' * * * равно ∞ при x -> 0 – SiegeX

+0

Это невероятно распространенная ошибка (я предполагаю, что люди, которые никогда не занимались формальным курсом исчисления, скорее всего, это.) SiegeX, C/C++ не имеет понятия «' -> '» – shoosh

+0

@shoosh: вы говорите, что 'lim [x -> +0] f (y)! = ∞', где 'f (y) = 1/x'? – SiegeX

11

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

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

+2

этот ответ не связан с программированием. –

+9

... это вполне правильный ответ, заданный вопросом. –

+6

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

1

У меня только проект C99. В § 7,12/4 он говорит:

Макро

INFINITY 

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

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

1

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

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

0

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


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

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

[От C99 станда (в конце проекта)] «неопределенное поведение: поведение, при использовании Непереносимой или ошибочной конструкции программы или ошибочных данных, для которых настоящего стандарт не накладывает никаких требований»

Примечания Существует " нет требования, предъявляемого к неопределенному поведению!

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

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

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

+0

Если реализация определяет '__STDC_IEC_559__', она должна внедрять семантику по-разному, совместимую с этим стандартом, даже если стандарт C не будет * иначе * навязывать какие-либо поведенческие требования. – supercat

1

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

  • В соответствии с IEEE 754. Стандарт на, что все современные компиляторы C/использование FPU, мы имеем
    • 3,0/0,0 = INF
    • 0,0/0,0 = NaN
    • -3,0/0,0 = -INF

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

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

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

0

Реализации, которые определяют __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 с противоположным знаком.

 Смежные вопросы

  • Нет связанных вопросов^_^