Целочисленное деление округления с отрицаниями в С++
Предположим, что 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
Значит, речь идет не только о стандарте, но есть только один способ, которым это может быть. Если какие-либо стандарты позволяют это быть любым другим способом, тогда стандарт ошибочен, и это означает, что язык сломан.