Целочисленное округление с делением на негативы в C ++ - PullRequest
30 голосов
/ 26 ноября 2008

Предположим, что a и b имеют тип int, а b не равен нулю. Рассмотрим результат выполнения a/b в следующих случаях:

  1. a и b оба неотрицательны.
  2. a и b оба являются отрицательными.
  3. Ровно один из них отрицательный.

В случае 1 результат округляется до ближайшего целого числа. Но что стандарт говорит о случаях 2 и 3? Старый черновик, который я обнаружил плавающим в Интернете, указывает на то, что он зависит от реализации (да, даже для случая 2), но комитет склоняется к тому, чтобы сделать его всегда «округленным к нулю». Кто-нибудь знает, что говорит (последний) стандарт? Пожалуйста, отвечайте только на основе стандарта, а не на то, что имеет смысл, или на то, что делают конкретные компиляторы.

Ответы [ 4 ]

22 голосов
/ 26 ноября 2008

Согласно майской редакции 2008 года,

Ты прав:

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

Примечание 75 гласит:

В соответствии с проводимой работой по пересмотру ISO C, предпочтительный алгоритм целочисленного деления следует правилам, определенным в стандарте ISO Fortran, ISO / IEC 1539: 1991, в котором частное всегда округляется до нуля.

Скорее всего, C ++ будет отставать от C в этом отношении. В его нынешнем виде он не определен, но они хотят его изменить.

Я работаю в том же отделе, что и Страуструп, и с членом комитета. Вещи требуют, чтобы возрасты были достигнуты, и это бесконечно политическое. Если это кажется глупым, это, вероятно, так.

18 голосов
/ 15 ноября 2011

В качестве обновления к другим ответам:

Последний черновик C ++ 11, n3242 , который для большинства практических целей идентичен фактическому стандарту C ++ 11, говорит об этом в 5.6 пункт 4 (стр. 118):

Для целых операндов оператор / дает алгебраический фактор с любой дробной частью отбрасывается; (см. примечание 80)

Примечание 80 состояний (обратите внимание, что примечания являются ненормативными):

80) Это часто называют усечением до нуля.

Пункт 4 продолжает утверждать:

если частное a / b представимо в типе результата, (a / b) * b + a% b равно a.

, который, как можно показать, требует, чтобы знак a%b совпадал со знаком a (если не ноль).

7 голосов
/ 26 ноября 2008

Просто комментарий. Текущий рабочий проект для стандарта C ++ действительно исправляет проблему, "определяемую реализацией", и требует усечения до нуля. Здесь - веб-страница комитета, а здесь - черновик. Вопрос на стр. 112.

0 голосов
/ 23 ноября 2017

Иногда нам нужно сделать шаг назад и посмотреть только на математику:

Учитывая int x, int y

если int i1 = x / y и int i2 = x% y

тогда y * i1 + i2 должно быть x

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

...