我试图对一个整数进行mod以获得一个数组位置,这样它就会循环。做i % arrayLength适用于正数,但对于负数就完全出错了。

 4 % 3 == 1
 3 % 3 == 0
 2 % 3 == 2
 1 % 3 == 1
 0 % 3 == 0
-1 % 3 == -1
-2 % 3 == -2
-3 % 3 == 0
-4 % 3 == -1

我需要一个实现

int GetArrayIndex(int i, int arrayLength)

这样

GetArrayIndex( 4, 3) == 1
GetArrayIndex( 3, 3) == 0
GetArrayIndex( 2, 3) == 2
GetArrayIndex( 1, 3) == 1
GetArrayIndex( 0, 3) == 0
GetArrayIndex(-1, 3) == 2
GetArrayIndex(-2, 3) == 1
GetArrayIndex(-3, 3) == 0
GetArrayIndex(-4, 3) == 2

我以前也这么做过,但不知为何,今天我的脑子都要融化了:(


当前回答

增加一些理解。

根据欧几里得的定义,取模的结果必须总是正的。

Ex:

 int n = 5;
 int x = -3;

 int mod(int n, int x)
 {
     return ((n%x)+x)%x;
 }

输出:

 -1

其他回答

单行实现只使用%一次:

int mod(int k, int n) {  return ((k %= n) < 0) ? k+n : k;  }

dcastro的答案的单行实现(与其他语言最兼容):

int Mod(int a, int n)
{
    return (((a %= n) < 0) && n > 0) || (a > 0 && n < 0) ? a + n : a;
}

如果你想保留%操作符的使用(在c#中你不能重载本机操作符):

public class IntM
{
    private int _value;

    private IntM(int value)
    {
        _value = value;
    }

    private static int Mod(int a, int n)
    {
        return (((a %= n) < 0) && n > 0) || (a > 0 && n < 0) ? a + n : a;
    }

    public static implicit operator int(IntM i) => i._value;
    public static implicit operator IntM(int i) => new IntM(i);
    public static int operator %(IntM a, int n) => Mod(a, n);
    public static int operator %(int a, IntM n) => Mod(a, n);
}

用例,两者都适用:

int r = (IntM)a % n;

// Or
int r = a % n(IntM);

这是我对正整数的一行代码,基于这个答案:

用法:

(-7).Mod(3); // returns 2

实现:

static int Mod(this int a, int n) => (((a %= n) < 0) ? n : 0) + a;

只需将您的模量(arrayLength)添加到%的负结果,就可以了。

请注意,c#和c++的%运算符实际上不是模数,而是余数。在你的例子中,求模的公式是:

float nfmod(float a,float b)
{
    return a - b * floor(a / b);
}

你必须用c#(或c++)重新编码,但这是你得到模数而不是余数的方法。