Как кодировать оператор по модулю (%) в C / C ++ / Obj-C, который обрабатывает отрицательные числа - PullRequest
79 голосов
/ 23 октября 2010

Одна из моих любимых ненавистей к C-производным языкам (как к математике) заключается в том, что

(-1) % 8 // comes out as -1, and not 7

fmodf(-1,8) // fails similarly

Какое лучшее решение?

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

Ответы [ 15 ]

0 голосов
/ 18 июля 2016

Пример шаблона для C ++

template< class T >
T mod( T a, T b )
{
    T const r = a%b;
    return ((r!=0)&&((r^b)<0) ? r + b : r);
}

При использовании этого шаблона возвращаемый остаток будет равен нулю или будет иметь тот же знак, что и делитель (знаменатель) (эквивалент округления в сторону отрицательной бесконечности) вместоC ++ поведение остатка, равного нулю или имеющего тот же знак, что и дивиденд (числитель) (эквивалент округления до нуля).

0 голосов
/ 06 февраля 2015

Это решение (для использования, когда mod положительно) позволяет избежать одновременного выполнения отрицательных операций деления или остатка:

int core_modulus(int val, int mod)
{
    if(val>=0)
        return val % mod;
    else
        return val + mod * ((mod - val - 1)/mod);
}
0 голосов
/ 17 марта 2014

Я бы сделал:

((-1)+8) % 8 

Это добавляет последнее число к первому перед выполнением по модулю, давая 7 по желанию. Это должно работать для любого числа до -8. Для -9 добавить 2 * 8.

0 голосов
/ 07 марта 2014
unsigned mod(int a, unsigned b) {
    return (a >= 0 ? a % b : b - (-a) % b);
}
0 голосов
/ 28 ноября 2012
define  MOD(a, b)       ((((a)%(b))+(b))%(b))
...