2016-09-05 3 views
4

Таким образом, существует три значения, что операция модуля может дать вам:C++ с отрицательным операндом

Тогда:

-7% 5 = 3 (математика, остальное> = 0)

-7% 5 = -2 (С ++)

-7% (size_t) 5 = 4 (C++)

Другой пример:

-7% 4 = 1 (математике, остальное> = 0)

-7% 4 = -3 (C++)

-7% (size_t) 4 = 1 (C++)

Когда левый операнд положительный, ответ между всеми тремя способами одинаковый. Но для отрицательных значений у всех, похоже, есть свои методы. Как вычисляется значение операций модуля для неподписанных операндов на C++?

+4

Ваши утверждения «математики» предполагают, что во всем мире математики есть только одно определение, которое, конечно же, неверно! –

+3

Операции с неподписанными типами никогда не могут принимать отрицательные операнды. – hvd

ответ

9

Это то, что происходит, когда вы смешиваете подписанные и неподписанные значения — путаница!

[C++14: 5.6/2]: Операнды * и / должны иметь арифметические или незаданной тип перечисления; , операнды % должны иметь тип перечисления с интегральным или незащищенным. Обычные арифметические преобразования выполняются над операндами и определяют тип результата.

Теперь увидеть жирный канал ниже (который предполагает, что ваша size_t имеет тот же ранг, что ваш int, это всегда верно):

[C++14: 5/10]: Многие бинарные операторы, которые ожидают операнды арифметической или перечисления тип вызывает преобразования и выводит типы результатов аналогичным образом. Цель состоит в том, чтобы дать общий тип, который также является типом результата. Эта модель называется обычных арифметических преобразований, которые определены следующим образом:

  • Если один из операндов имеют Scoped типа перечисления (7.2), преобразование не выполняются; если другой операнд не имеет одного и того же типа, выражение плохо сформировано.
  • Если один из операндов имеет тип long double, другой должен быть преобразован в длинный двойной.
  • В противном случае, если один из операндов двойной, другой должен быть преобразован в двойной.
  • В противном случае, если любой операнд поплавковый, другой должен быть преобразован в поплавок.
  • В противном случае, интегральные акции (4.5), должны быть выполнены на обеих operands.61 Тогда следующие правила должны применяться к операндам продвигаемых:
    • Если оба операнда имеют один и тот же тип, никакие дальнейшие преобразования не требуется ,
    • В противном случае, если оба операнда имеют целочисленные типы или оба имеют неподписанные целые типы, операнд с типом ранга меньшего целочисленного преобразования преобразуется в тип операнда с большим рангом.
    • В противном случае , если операнд, имеющий целочисленный тип без знака, имеет ранг, больший или равный рангам типа другого операнда, операнд со знаком целочисленного типа преобразуется в тип операнда с целым числом без знака ,
    • В противном случае, если тип операнда со знаком целочисленного типа может представлять все значения типа операнда с целым числом без знака, операнд с целым типом без знака преобразуется в тип операнда со знаком целочисленный тип.
    • В противном случае оба операнда должны быть преобразованы в целочисленный тип без знака, соответствующий типу операнда со знаком целочисленного типа.

Короче говоря, ваш -7 становится std::numeric_limit<size_t>::max() + 1 - 7 (независимо от того, что на вашей платформе), а расчет выполняется на этом значении. Действительно, on my platform, that confirms the result of 1.

+0

Поэтому я должен написать свою собственную функцию мод, чтобы все было согласовано. Благодарю. – Dobob

+3

@Dobob Вы не должны смешивать беззнаковые и подписанные математики бездумно. – Serge

+2

@Dobob: Это вовсе не отговорка от этого. Серж правильно. –