Каково поведение C89 в отношении целочисленного деления двух отрицательных чисел: округление вверх, округление вниз или не определено? - PullRequest
0 голосов
/ 27 апреля 2018

Например,

Если я напишу

int var;
var=-8/-5;

В соответствии с приоритетом оператора, -8 / -5 будет эквивалентно ((-8) / (- 5)). Но сможет ли C89 дать два значения, как для случая -8/5, он может дать -1 или -2. или это будет трактоваться как деление двух натуральных чисел?

Вопрос со ссылкой на книгу К.Н.Кинга (C Programming A современный подход)

Ответы [ 4 ]

0 голосов
/ 27 апреля 2018

Из второго издания K & R (около 1988 г.)

Бинарный оператор / дает частное, а оператор % остаток от деления первого операнда на второй; если второй операнд равен 0, результат не определен, в противном случае он всегда правда, что (a/b)*b + a%b равно a. Если оба операнда неотрицательный, то остаток неотрицательный и меньше, чем делитель; если нет, то гарантируется только то, что абсолютное значение остаток меньше абсолютного значения делителя.

Например, для вычисления -8/-5 (по правилам C89) нам сначала нужно вычислить -8%-5. Спецификация допускает два возможных ответа для остатка: -3 и 2. Оба удовлетворяют требованию, что абсолютное значение остатка меньше, чем абсолютное значение делителя, и оба удовлетворяют требованию, что (a/b)*b + a%b равно a.

(-8/-5)*-5 + -3 = -8    ==>    (-8/-5) = 1     since    (1)*-5 + -3 = -8
(-8/-5)*-5 +  2 = -8    ==>    (-8/-5) = 2     since    (2)*-5 +  2 = -8

Таким образом, результат деления позволил (C89) иметь два разных ответа, потому что (при условии отрицательного a или b) результат оператора остатка % может быть либо отрицательным, либо положительным. Это было исправлено в C99, которое требует деления для усечения до 0.


Для тех, кто склонен к математике, обратите внимание, что

-3 ≣ 2 mod(5)

https://en.wikipedia.org/wiki/Congruence_relation

0 голосов
/ 27 апреля 2018

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

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

0 голосов
/ 27 апреля 2018

Каково поведение С89 относительно деления двух отрицательных чисел

Коэффициент будет 1 или 2.

int var;
var=-8/-5;

C89 допускает деление 2 целых чисел (по крайней мере с одним отрицательным), которые имеют ненулевой остаток до результата более высокого или более низкого целого числа. Стандартная библиотека предоставила div() для последовательного вычисления коэффициента и остатка по компиляторам без такой гибкости.

div_t     div( int x, int y );

У этой функции было задано «усечение до нуля», что является поведением / с C99. Это позволило переносить, хотя иногда немного неэффективно, код C89.

0 голосов
/ 27 апреля 2018

C89 имеет правило, что если любой операнд отрицателен, то результат деления может быть округлен в большую или меньшую сторону.
C89-3.3.5:

Если любой из операндов отрицателен, то, является ли результат оператора / наибольшим целым числом, меньшим, чем алгебраический фактор, или наименьшим целым числом, большим, чем алгебраический фактор, определяется реализацией, как и знак результата % оператор. Если частное a/b представимо, выражение (a/b)*b + a%b должно равняться a.

Например, в случае -8/5; Выход может быть -1 ((-8)/5) или -2 (-(8/5)).
В C99 он гарантированно обрезается до 0.

В вашем случае оба операнда являются -ve, а выводом будет число + ve (в данном случае 1 или 2).

...