Jaka jest różnica między „mod” a „reszta”?

140

Mój przyjaciel powiedział, że istnieją różnice między „mod” a „reszta”.

Jeśli tak, jakie są te różnice w C i C ++? Czy „%” oznacza „mod” lub „rem” w C?

songhir
źródło
2
Prawdopodobnie jest źle zdefiniowany dla argumentów ujemnych.
Basile Starynkevitch
1
Nie jestem osobą C :( więc nie mogę odpowiedzieć na to pytanie w polu odpowiedzi. Ale proszę spojrzeć na ten artykuł :)
bonCodigo
1
% to reszta. Szczegóły odpowiedzi tutaj -> blogs.msdn.com/b/ericlippert/archive/2011/12/05/…
wim
1
Pytanie nic nie znaczy, dopóki nie zdefiniujesz dokładnie, co oznaczają te terminy.
David Heffernan
14
@David: pytanie dotyczy znaczenia terminów. Jeśli powiesz, że pytanie nie ma żadnego znaczenia, pomimo tego, że kilka osób rozumie je w sposób zamierzony przez pytającego, to myślę, że musisz sprecyzować, co masz na myśli, mówiąc o tym ;-)
Steve Jessop

Odpowiedzi:

147

Istnieje różnica między modułem a resztą. Na przykład:

-21mod 4jest, 3ponieważ -21 + 4 x 6jest 3.

Ale -21podzielone przez 4daje -5z resztą -1.

W przypadku wartości dodatnich nie ma różnicy.

David Schwartz
źródło
22
% oznacza rem w C.
banuj
22
@Jinxiao: w C89 było to zdefiniowane przez implementację: %było to zawsze reszta, ale może to być również moduł (tj. Zawsze dodatni), ponieważ w C89 dzielenie liczb całkowitych było dozwolone zaokrąglać w kierunku ujemnej nieskończoności zamiast w kierunku 0. Tak więc w C89, -5 / 2może być -2z resztą -1lub -3z resztą 1, implementacja musiała tylko udokumentować, które. C99 usunął elastyczność, więc teraz -5 / 2jest zawsze -2.
Steve Jessop
2
Właściwie nie jest jasne, co to jest moduł. Wydaje się, że istnieje wiele różnych definicji, w zależności od kontekstu i języka. Zobacz artykuł wikipedii o modulo_operation. W niektórych kontekstach jest w rzeczywistości taki sam jak w pozostałych.
Rudy Velthuis,
10
Czy ktoś może wyjaśnić kroki w pierwszym obliczeniu? Jaki jest -21mod ? Dlaczego obliczenia są ? 43-21 + 4 x 6
Oz Edri
14
@OzEdri Aby uzyskać mod 4, dodajesz dowolną całkowitą wielokrotność 4, aby uzyskać liczbę od 0 do 3. Dla -21, ta liczba całkowita wynosi 6, ponieważ -21 + 4 x 6jest między 0 a 3.
David Schwartz
50

Czy „%” oznacza „mod” lub „rem” w C?

W C %jest reszta 1 .

..., wynikiem /operatora jest iloraz algebraiczny z odrzuconą dowolną częścią ułamkową ... (Jest to często nazywane „obcięciem w kierunku zera”). C11dr §6.5.5 6

Operandy %operatora są typu całkowitego. C11dr §6.5.5 2

Wynikiem /operatora jest iloraz z dzielenia pierwszego argumentu przez drugi; wynikiem %operatora jest reszta ... C11dr §6.5.5 5


Jaka jest różnica między „mod” a „reszta”?

C nie definiuje „mod”, na przykład funkcji modułu całkowitego używanej w dzieleniu euklidesowym lub w innych modulo . „Mod euklidesowy” różni się od a%boperacji C, gdy ajest ujemny.

 // a % b
 7 %  3 -->  1  
 7 % -3 -->  1  
-7 %  3 --> -1  
-7 % -3 --> -1   

Modulo jako podział euklidesowy

 7 modulo  3 -->  1  
 7 modulo -3 -->  1  
-7 modulo  3 -->  2  
-7 modulo -3 -->  2   

Kandydat na kod modulo:

int modulo_Euclidean(int a, int b) {
  int m = a % b;
  if (m < 0) {
    // m += (b < 0) ? -b : b; // avoid this form: it is UB when b == INT_MIN
    m = (b < 0) ? m - b : m + b;
  }
  return m;
}

Uwaga na temat zmiennoprzecinkowych: double fmod(double x, double y)chociaż nazywa się to „fmod”, nie jest to to samo, co dzielenie euklidesowe „mod”, ale jest podobne do reszty liczby całkowitej C:

Te fmod funkcje obliczenia zmiennoprzecinkowe resztę x/y. C11dr §7.12.10.1 2

fmod( 7,  3) -->  1.0  
fmod( 7, -3) -->  1.0  
fmod(-7,  3) --> -1.0  
fmod(-7, -3) --> -1.0   

Ujednoznacznienie : C ma również podobną nazwaną funkcję, double modf(double value, double *iptr)która dzieli wartość argumentu na części całkowite i ułamkowe, z których każda ma ten sam typ i znak jak argument. To ma niewiele wspólnego z dyskusją o "modach" poza podobieństwem nazw.


1 Przed C99, definicja C %nadal była pozostałością z dzielenia, ale wtedy /pozwalała ujemnym ilorazom na zaokrąglenie w dół zamiast „obcięcia w kierunku zera”. Zobacz Dlaczego otrzymujesz różne wartości dzielenia liczb całkowitych w C89? . Tak więc w przypadku niektórych kompilacji sprzed C99 %kod może działać tak, jak „mod” działu euklidesowego. Powyższe modulo_Euclidean()będzie działać również z tą alternatywną pozostałością ze starej szkoły.

chux - Przywróć Monikę
źródło
1
Aby zaimplementować podział euklidesowy i funkcje modulo w C, zobacz Podział i moduł dla informatyków . Może działać szybciej, jeśli wiesz, że tylko twoja dywidenda może być ujemna, ale twój dzielnik jest zawsze dodatni: godbolt.org/g/63UqJo . Powiązane: pytanie asm x86 z prośbą o nieujemne modulo
Peter Cordes
Zwykła definicja operatora modulo jest bardziej podobna do:
Mike Housky
3

W C i C ++ oraz wielu językach, % reszta NIE jest operatorem modułu.

Na przykład w operacji -21 / 4część całkowita to, -5a część dziesiętna to -.25. Reszta to część ułamkowa pomnożona przez dzielnik, więc nasza reszta to -1. JavaScript używa operatora reszty i potwierdza to

console.log(-21 % 4 == -1);

Operator modułu działa tak, jakbyś miał „zegar”. Wyobraź sobie okrąg z wartościami 0, 1, 2 i 3 odpowiednio na godzinie 12, 3, 6 i 9. Podnoszenie ilorazu razy w kierunku zgodnym z ruchem wskazówek zegara daje nam wynik działania modułu lub, w naszym przykładzie, z ilorazem ujemnym, przeciwnie do ruchu wskazówek zegara, dając 3.

Uwaga: moduł jest zawsze tym samym znakiem co dzielnik, a pozostała część jest tym samym znakiem co iloraz. Dodanie dzielnika i reszty, gdy przynajmniej jeden jest ujemny, daje moduł.

theEpsilon
źródło
Czy chodziło Ci o to, że znak pozostałej części jest zawsze tym samym znakiem co dywidenda ? Iloraz 7 / -3 = -2, ale 7 rem -3 = 1.
dx_over_dt
2

Moduł, w arytmetyce modularnej, o którym mówisz, jest wartością pozostałą lub pozostałą wartością po dzieleniu arytmetycznym. Jest to powszechnie znane jako reszta. % jest formalnie operatorem reszty w C / C ++. Przykład:

7 % 3 = 1  // dividend % divisor = remainder

Pozostaje do dyskusji, jak traktować negatywne dane wejściowe w tej operacji%. Nowoczesne C i C ++ tworzą dla tej operacji znak reszty ze znakiem, w którym znak wyniku zawsze pasuje do wejściowej dywidendy bez względu na znak wejściowy dzielnika.

user487158
źródło
-3

W matematyce wynik operacji modulo jest pozostałą częścią podziału euklidesowego. Jednak możliwe są inne konwencje. Komputery i kalkulatory mają różne sposoby przechowywania i przedstawiania liczb; w związku z tym ich definicja operacji modulo zależy od języka programowania i / lub używanego sprzętu.

 7 modulo  3 -->  1  
 7 modulo -3 --> -2 
-7 modulo  3 -->  2  
-7 modulo -3 --> -1 
shub sharma
źródło
2
Podział wiki Euklidesa twierdzi, 0 ≤ r < |b|że reszta jest znana jako „operacja modulo”. wynosi zawsze co najmniej 0. Jakiej definicji używasz, która daje -2 i -1?
chux - Przywróć Monikę
proszę pana, nie, nie, ale po prostu google 7 modulo -3 -> -2. i -7 modulo -3 -> -1 proszę wyjaśnić proszę pana, dlaczego tak się stało
shub sharma
1
Google używa innej definicji modulo (ze znakiem modulo?) Niż oddział Wiki Euclidean (opisany przez Raymonda T. Boute'a). To bardziej omawia różnice. Morał z tej historii: a%bi a modulo bmają to samo znaczenie, gdy a,bsą pozytywne. C99 definiuje %precyzyjnie za pomocą wartości ujemnych. C nazywa to „resztą”. „Modulo” ma różne definicje na świecie dotyczące wartości ujemnych. C spec używa tylko „modulo” w kontekście liczb dodatnich.
chux - Reinstate Monica