[C#] 음수의 모드는 내 뇌를 녹이고있다

배열 위치를 얻기 위해 정수를 수정하여 루프가 순환되도록합니다. 이렇게 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

나는 전에 이것을했지만 어떤 이유로 든 오늘 내 두뇌가 녹고있다 🙁



답변

나는 항상 내 자신의 mod기능을 사용합니다.

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

물론, 모듈러스 연산 에 대한 두 번의 호출이 걱정된다면 , 다음과 같이 쓸 수 있습니다.

int mod(int x, int m) {
    int r = x%m;
    return r<0 ? r+m : r;
}

또는 이의 변형.

작동하는 이유는 “x % m”이 항상 [-m + 1, m-1] 범위에 있기 때문입니다. 따라서 음수이면 m을 추가하면 값 modulo m을 변경하지 않고 양수 범위에 놓입니다.


답변

C #과 C ++의 % 연산자는 실제로 모듈로가 아니며 나머지입니다. 원하는 경우 모듈로의 공식은 다음과 같습니다.

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

이것을 C # (또는 C ++)으로 다시 코딩해야하지만 나머지가 아닌 모듈로를 얻는 방법입니다.


답변

%한 번만 사용하는 단일 라인 구현 :

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


답변

부정적인 배당 / 제수를 설명하는 경우 “if (m <0) m = -m;”을 추가하더라도 ShreevatsaR의 답변은 모든 경우에 적용되지 않습니다.

예를 들어, -12 mod -10은 8이고 -2 여야합니다.

다음 구현은 양수 및 음수 배당 / 제수 모두에 대해 작동하며 다른 구현 (즉, Java, Python, Ruby, Scala, Scheme, Javascript 및 Google 계산기)을 준수합니다.

internal static class IntExtensions
{
    internal static int Mod(this int a, int n)
    {
        if (n == 0)
            throw new ArgumentOutOfRangeException("n", "(a mod 0) is undefined.");

        //puts a in the [-n+1, n-1] range using the remainder operator
        int remainder = a%n;

        //if the remainder is less than zero, add n to put it in the [0, n-1] range if n is positive
        //if the remainder is greater than zero, add n to put it in the [n-1, 0] range if n is negative
        if ((n > 0 && remainder < 0) ||
            (n < 0 && remainder > 0))
            return remainder + n;
        return remainder;
    }
}

xUnit을 사용한 테스트 스위트 :

    [Theory]
    [PropertyData("GetTestData")]
    public void Mod_ReturnsCorrectModulo(int dividend, int divisor, int expectedMod)
    {
        Assert.Equal(expectedMod, dividend.Mod(divisor));
    }

    [Fact]
    public void Mod_ThrowsException_IfDivisorIsZero()
    {
        Assert.Throws<ArgumentOutOfRangeException>(() => 1.Mod(0));
    }

    public static IEnumerable<object[]> GetTestData
    {
        get
        {
            yield return new object[] {1, 1, 0};
            yield return new object[] {0, 1, 0};
            yield return new object[] {2, 10, 2};
            yield return new object[] {12, 10, 2};
            yield return new object[] {22, 10, 2};
            yield return new object[] {-2, 10, 8};
            yield return new object[] {-12, 10, 8};
            yield return new object[] {-22, 10, 8};
            yield return new object[] { 2, -10, -8 };
            yield return new object[] { 12, -10, -8 };
            yield return new object[] { 22, -10, -8 };
            yield return new object[] { -2, -10, -2 };
            yield return new object[] { -12, -10, -2 };
            yield return new object[] { -22, -10, -2 };
        }
    }


답변

이해력 향상.

으로 유클리드의 정의 유행의 결과는 항상 양수 여야합니다.

전의:

 int n = 5;
 int x = -3;

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

산출:

 -1


답변

두 가지 주요 답변 비교

(x%m + m)%m;

int r = x%m;
return r<0 ? r+m : r;

실제로 첫 번째 것은 OverflowException잠시 동안 던질 수 있고 두 번째는 그렇지 않을 것이라는 사실을 언급 한 사람은 없습니다. 더 나쁜 것은 기본 확인되지 않은 컨텍스트를 사용하면 첫 번째 답변이 잘못된 답변을 반환 할 수 있습니다 ( mod(int.MaxValue - 1, int.MaxValue)예 : 참조 ). 따라서 두 번째 대답은 더 빠를뿐만 아니라 더 정확한 것처럼 보입니다.


답변

모듈러스 (arrayLength)를 %의 음수 결과에 추가하기 만하면됩니다.