2012-04-08 14 views
25

Oggi stavo scrivendo un programma in C#, e ho usato % per calcolare qualche indice ... Il mio programma non ha funzionato, così ho il debug e mi sono reso conto che "%" non funziona come nelle altre lingue del programma che conosco.% (mod) spiegazione

Ad esempio:

In Python valori % restituisce come questo:

for x in xrange (-5, 6): 
    print x, "% 5 =", x % 5 

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

in C#:

for (int i = -5; i < 6; i++) 
{ 
    Console.WriteLine(i + " % 5 = " + i % 5); 
} 

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

ho fatto qualcosa di sbagliato o è % non funziona come dovrebbe?

+36

In linguaggi C-derivati,% non è l'operatore modulo. È l'operatore * resto *. [Eric Lippert spiega] (http://blogs.msdn.com/b/ericlippert/archive/2011/12/05/what-s-the-difference-remainder-vs-modulus.aspx). –

+8

@RaymondChen che sembra una risposta, non un commento. Posso prevederlo, se vuoi, però. –

+1

Come posso utilizzare l'operatore modulo in C#? – Wolfy

risposta

13

Come spiegato nei commenti, il diverso comportamento è di progettazione. Le diverse lingue attribuiscono semplicemente significati diversi all'operatore %.

vi chiedo:

Come posso usare operatore modulo in C#?

è possibile definire un operatore modulo te stesso che si comporta lo stesso era come l'operatore Python %:

int mod(int a, int n) 
{ 
    int result = a % n; 
    if ((a<0 && n>0) || (a>0 && n<0)) 
     result += n; 
    return result; 
} 
+7

Il tuo codice restituisce risultati errati, ad esempio mod (-5, 5) == 5. Per un esempio funzionante, consulta questa [risposta] (http://stackoverflow.com/questions/1082917/mod-of-negative-number -is-melting-my-brain) – Drake

5

Entrambe le risposte sono corrette. Anche se personalmente penso che il "sempre positivo" abbia più senso.

È possibile definire la propria funzione modulo che dà solo risposte positive come questa:

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

cosa restituisce 'mod (-5, 2)'? –

+0

Dannazione ... Ok, fammi riprovare. –

+1

'mod (-2, -5)' restituisce -2. Hai detto che dovrebbe restituire sempre valori positivi, ma ci sono input che causano il ritorno di valori negativi. È accettabile? È previsto? –

4

In modular arithmetic, si definisce classi di numeri sulla base del modulo. In altre parole, nel modulo m aritmetiche, un numero n è equivalente (leggi: la stessa) a n + m, n - m, n + 2m, n - 2m, ecc

soltanto definisce m "panieri" e ogni numero cade in uno (e uno solo) di loro.

Esempio: si può dire "E '16:30" oppure si può dire "E' 16:30". Entrambe le forme significano esattamente lo stesso tempo, ma sono diverse rappresentazioni di esso.

Quindi entrambi i risultati di Python e C# sono corretti!I numeri sono lo stesso nel modulo aritmetica che hai scelto. Sarebbe anche stato matematicamente corretto per restituire (5, 6, 7, 8, 9) per esempio. Solo un po 'strano.

Per quanto riguarda la scelta della rappresentazione (in altre parole, la scelta su come rappresentare i numeri negativi), questo è solo un caso di scelte progettuali diverse tra le due lingue.

Tuttavia, ciò non è affatto ciò che l'operatore% in realtà fa in C#. L'operatore% non è l'operatore del modulo canonico; è il resto dell'operatore. L'operatore A% B risponde effettivamente alla domanda "Se dividessi A per B usando l'aritmetica dei numeri interi, quale sarebbe il resto?"

What's the difference? Remainder vs Modulus by Eric Lippert


frammento veloce per ottenere il modulo canonica:

return ((n % m) + m) % m; 

implementazione di prova:

Mono/C#:

machine:~ user$ cat mod.cs 
using System; 

public class Program 
{ 
    public static void Main (string[] args) 
    { 
     Console.WriteLine(Mod(-2, 5)); 
     Console.WriteLine(Mod(-5, 5)); 
     Console.WriteLine(Mod(-2, -5)); 
    } 

    public static int Mod (int n, int m) 
    { 
     return ((n % m) + m) % m; 
    } 
} 

machine:~ user$ mono mod.exe 
3 
0 
-2 

Python:

machine:~ user$ cat mod.py 
print -2%5; 
print -5%5; 
print -2%-5; 

machine:~ user$ python mod.py 
3 
0 
-2 
+1

Che cos'è il "modulo canonico" di -2 e -5? Il tuo programma dà -2, ma penso che tu intendessi dare risultati non negativi. Cura di riprovare? –

+0

@EricLippert Non lo fa. Restituisce 3 e 0, rispettivamente. Vedi la mia modifica. – Sklivvz

+1

Ti assicuro, il tuo frammento dice che il modulo canonico di -2 e -5 è -2. Provalo: 'class P {static void Main() {int n = -2, m = -5; System.Console.WriteLine (((n% m) + m)% m)); }} Esegui, otterrai -2 stampato. Se era tua intenzione che il modulo canonico fosse non negativo, non sei riuscito a raggiungere la tua intenzione. Cura di riprovare? –