Целочисленное деление округления с отрицаниями в С++

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

  • a и b являются неотрицательными.
  • a и b являются отрицательными.
  • Именно один из них отрицательный.

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

Ответ 1

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

Вы правы:

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

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

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

Скорее всего, С++ будет отставать от C в этом отношении. Как бы то ни было, это undefined, но они имеют глаза на его изменение.

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

Ответ 2

Как дополнение к другим ответам:

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

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

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

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

Пункт 4 переходит в состояние:

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

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

Ответ 3

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

Ответ 4

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

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

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

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

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