2014-09-27 2 views

ответ

8

Проще говоря, вы взяли неправильный оператор.

C++ и C %не modulo, но остаток.

assert(a/b * b + a % b == a); // for integral types 

Если a является неотрицательным, по модулю, а остальные являются одинаковыми.

В противном случае возвращаемое значение отрицательно, просто добавьте b.

template<class T> 
inline constexpr auto 
modulo(T a, T b) -> decltype(a%b) { 
    auto r = a % b; 
    if(r<0) r += b; 
    return r; 
} 

Или (также) для C:

#define modulo(a, b) (a%b<0 ? a%b+b : a%b) 

Для полноты: Перед тем как C++ 11, a/b может всегда округлять вниз вместо того, чтобы всегда 0, хотя C++ 03 уже примечание что следующий стандарт будет, вероятно, санкционировать округление до 0.

Wikipedia on modulo:

Modulo остаток от деления euclidiean, и всегда в диапазоне от 0 < = по модулю < делителем

+1

Существует соответствующее определение 'а/b' таким образом, что' а/Ь * Ь + а% Ь == a' имеет значение true, когда '%' выполняет операцию, которую вы вызываете по модулю. До C++ 11 было определено конкретное определение 'a/b' и' a% b'. C++ 11 теперь указывает, что деление обеспечивает алгебраическое отношение, усеченное к нулю, что исключает '%', являющуюся операцией, которую вы вызываете по модулю. – bames53

+0

теперь я понимаю разницу. вы можете показать пример использования modulo в C++ –

+0

Чтобы справиться с 'a <0 && b <0', предложите' if (r <0) {m = r <0? m - r: m + r; } 'вместо' if (r <0) r + = b; ' – chux

0

функция, которая обрабатывает Модульное отрицательные делители, а также положительные делители:

template<class T> 
inline constexpr auto 
modulo(T a, T b) -> decltype(a%b) { 
    auto r = a % b; 
    if((b > 0 && r < 0) || (b < 0 && r > 0)) 
     r += b; 
    return r; 
} 
Смежные вопросы