Округление целочисленного деления с минусами в C ++

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

  1. a и b неотрицательны.
  2. a и b отрицательны.
  3. Ровно одно из них отрицательное.

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


person Community    schedule 26.11.2008    source источник
comment
Невероятная возможность исследования, учитывая характер стандарта на 1200 страниц. Я собираюсь дать ему быстрый grep и сдамся :)   -  person Stefan Mai    schedule 26.11.2008


Ответы (4)


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

Ты прав:

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

Примечание 75 говорит:

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

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

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

person Stefan Mai    schedule 26.11.2008
comment
Цитируемое заявление устарело. Он восходит к стандарту C ++ 98 и относится к версии C99. C99 определяет округление в сторону нуля, а C ++ 11 следует этому примеру. - person Jed; 29.05.2012

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

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

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

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

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

В пункте 4 говорится:

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

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

person Sjoerd    schedule 15.11.2011

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

person Federico A. Ramponi    schedule 26.11.2008

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

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

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

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

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

person user3283405    schedule 23.11.2017
comment
То, что вы говорите, правда, но это не отвечает на вопрос. Python и C ++ определяют целочисленное деление и модуль по модулю в соответствии с тем, что вы говорите, но в одном используется деление по полу, а в другом - с округлением до нуля, поэтому они не демонстрируют одинакового поведения. - person Kevin; 20.02.2020
comment
Это может быть правдой несколькими способами. Этот вопрос также касается значения x % y. Можно потребовать, чтобы для положительного y было 0 <= x % y < y, что вы, вероятно, имеете в виду и что я бы предпочел. Однако, как показывает правильный ответ, C ++ 11 на самом деле имеет для положительного значения y 0 <= | x % y | < y, а знак x равен знаку x % y (если не равен нулю), - person Carsten S; 13.03.2020