Am'm încercând să-mod un număr întreg pentru a obține o serie de poziție, astfel încât acesta va buclă rotundă. Face i % arrayLength
funcționează bine pentru numere pozitive, dar pentru numere negative totul merge bine.
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
deci am nevoie de o punere în aplicare a
int GetArrayIndex(int i, int arrayLength)
astfel că
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
Am'am făcut acest lucru înainte, dar pentru unii motiv,'s topire creierul meu de azi :(
Eu folosesc întotdeauna propriul meu " mod " funcția, definită ca
int mod(int x, int m) {
return (x%m + m)%m;
}
Desigur, daca're deranjat despre două apeluri la modul de funcționare, ai putea scrie ca
int mod(int x, int m) {
int r = x%m;
return r<0 ? r+m : r;
}
sau variante ale acestora.
Motivul pentru care funcționează este că "x%m" este întotdeauna în intervalul [-m+1, m-1]. Deci, dacă acesta este negativ, adăugând m pentru a va pune in intervalul pozitiv, fără a schimba valoarea sa modulo m.
Vă rugăm să rețineți că C# și C++'s % operator este de fapt o modulo, l's rest. Formula pentru modulo pe care doriți, în cazul tău, este:
float nfmod(float a,float b)
{
return a - b * floor(a / b);
}
Trebuie să recode acest lucru în C# (sau C++), dar acest lucru este modul în care obține modulo și nu un rest.
Adăugarea de puțină înțelegere.
De Euclidiene definiție mod rezultatul trebuie să fie întotdeauna pozitiv.
Ex:
int n = 5;
int x = -3;
int mod(int n, int x)
{
return ((n%x)+x)%x;
}
Ieșire:
-1
ShreevatsaR's a răspunde câștigat't de lucru pentru toate cazurile, chiar dacă adăugați "dacă(m<0) m=-m;", daca tii cont de negative dividende/divizori.
De exemplu, -12 mod -10 va fi de 8, și ar trebui să fie -2.
Următoarele implementare va lucra pentru atât pozitive, cât și negative dividende / divizori și în conformitate cu alte implementări (și anume, Java, Python, Ruby, Scala, Schema, Javascript și Google's Calculator):
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;
}
}
Test suite folosind 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 };
}
}
Pentru mai performanta conștienți devs
uint wrap(int k, int n) ((uint)k)%n
O mică comparație a performanței
Modulo: 00:00:07.2661827 ((n%x)+x)%x)
Cast: 00:00:03.2202334 ((uint)k)%n
If: 00:00:13.5378989 ((k %= n) < 0) ? k+n : k
Ca pentru performanță costul de distributie a uint avea o privire de aici
Compararea a două predominant răspunsuri
(x%m + m)%m;
și
int r = x%m;
return r<0 ? r+m : r;
De fapt, nimeni nu a menționat faptul că primul poate arunca un OverflowException în timp ce, în cel de-al doilea a câștigat't. Chiar mai rău, cu default necontrolat context, primul răspuns ar putea reveni răspunsul greșit (a se vedea
mod(int.MaxValue - 1, int.MaxValue)` de exemplu). Deci, al doilea răspuns nu numai că pare să fie mai rapid, dar, de asemenea, mai corect.
Îmi place trucul prezentat de Peter N Lewis pe acest thread: "Dacă n-are o gamă limitată, atunci puteți obține rezultatul dorit, pur și simplu prin adăugarea unui cunoscut constanta multiple de [divizor] care este mai mare ca valoarea absolută minimă."
Deci, dacă am avea o valoare d, care este în grade și vreau să-l iau
d % 180f
și vreau să evit problemele, dacă d este negativ, atunci în loc să fac asta:
(d + 720f) % 180f
Aceasta presupune că, deși d poate fi negativ, este cunoscut faptul că niciodată nu va fi mai mult negative decât -720.
Am observat Un lucru. Este oferindu-doar numere pozitive în python
imprimare 4%3 print 3%3 print 3%3 imprimare 2%3 imprimare 1%3 print 0%3 imprimare -1%3 imprimare -2%3 imprimare -3%3 imprimare -4%3
- asta mi-a dat
1 Zero Zero Două Unul Zero Două Unul Zero Două
Dar În C, este de a da răspunsurile date de @gormenghastly
#include<stdio.h>
int main()
{
printf("\n %d",3 % 3);
printf("\n %d",4 % 3);
printf("\n %d",3 % 3);
printf("\n %d",2 % 3);
printf("\n %d",1 % 3);
printf("\n %d", 0 % 3);
printf("\n %d",-1 % 3);
printf("\n %d",-2 % 3);
printf("\n %d",-3 % 3);
printf("\n %d",-4 % 3);
return 0;
}
Am fost a face definiția % din ceea ce am putut vedea din python ieșire, Dar acum eu sunt, de asemenea, confuz
Toate răspunsurile aici mare lucru dacă este divizor pozitiv, dar's nu destul de complet. Aici este punerea în aplicare a mea care se întoarce mereu pe o serie de `[0, b), astfel încât semnul de ieșire este aceeași ca semn al divizor, pentru a permite negative divizori ca endpoint pentru gama de ieșire.
PosMod(5, 3)
a se întoarce 2
PosMod(-5, 3)
a se întoarce 1
PosMod(5, -3)
a se întoarce -1
PosMod(-5, -3)
a se întoarce -2
/// <summary>
/// Performs a canonical Modulus operation, where the output is on the range [0, b).
/// </summary>
public static real_t PosMod(real_t a, real_t b)
{
real_t c = a % b;
if ((c < 0 && b > 0) || (c > 0 && b < 0))
{
c += b;
}
return c;
}
(unde real_t` poate fi orice tip de număr)