Mod în Java produce numere negative [duplicate] (Programare, Java, Math, Mod)

Christian a intrebat.
a intrebat.

Când calculez int i = -1 % 2 obțin -1 în Java. În Python, obțin 1 ca rezultat al -1 % 2.ce trebuie să fac pentru a obține același comportament în Java cu funcția modulo?

Comentarii

  • Stai, de fapt, aceasta este o întrebare duplicată. Ea are și un răspuns perfect stackoverflow.com/a/4412200/1083704…  > Por Val.
  • @Val ai menționat clasele de echivalență modulo n: acest interval {0,1,2..n-1} este bun pentru programatori, dar {-n,n+1,n+2,-1} este echivalent și are același drept de a exista –  > Por Timofey.
  • Fără îndoială, o parte din confuzie provine din denumirea noastră colocvială „mod” pentru acest operator (rămasă din familia C?), când documentația Java îl numește de fapt operatorul „rest” (docs.oracle.com/javase/tutorial/java/nutsandbolbolts/op1.html) –  > Por LarsH.
  • K&R C definește operatorul % ca producând rezultatul restul, dar îl numește modul operator de modul. În mod confuz, ro.wikipedia.org/wiki/Modulo_operation spune că operatorul modulo produce operația restul, atât în informatică, cât și în matematică… dar susține și că „Intervalul numerelor pentru un întreg modulo de n este de la 0 la n – 1.”! –  > Por LarsH.
  • În Java nu există un operator modulus. % este un operator de rest. –  > Por user207421.
5 răspunsuri
andrewmu

Problema aici este că în Python operatorul % returnează operatorul %. modulul iar în Java acesta returnează restul. Aceste funcții dau aceleași valori pentru argumente pozitive, dar modulul returnează întotdeauna rezultate pozitive pentru intrări negative, în timp ce restul poate da rezultate negative. Există mai multe informații despre acest lucru în această întrebare.

Puteți găsi valoarea pozitivă procedând astfel:

int i = (((-1 % 2) + 2) % 2)

sau așa:

int i = -1 % 2;
if (i<0) i += 2;

(evident, -1 sau 2 poate fi orice doriți să fie numitorul sau numitorul)

Comentarii

  • @amit_gr – nu, cred că funcționează în general –  > Por andrewmu.
  • aveți dreptate – greșeala mea. +1 –  > Por amit.
  • @Cachapa vă rugăm să oferiți un exemplu care să susțină această afirmație. Cred că soluția lui OP este deja generală, luați în considerare faptul că (((-3 % 4) + 4) % 4) = 1 (rezultatul dorit) și, de asemenea, că (((3 % 4) + 4) % 4) = 3 (de asemenea, rezultatul urmărit). Funcționează atât cu dividende pozitive, cât și cu dividende negative. –  > Por The111.
  • @The111 Imaginează-ți că intervalul numărului tău întreg este [-8, 7], ((((5 % 6) + 6) % 6) = ((5 + 6) % 6) = (-5 % 6) = -5, dar 5 % 6 ar trebui să fie pozitiv. Înlocuiți numere suficient de mari pentru inții de 32 de biți, cum ar fi 536887296 și 1610612736 și este clar că a doua metodă este cea mai bună. –  > Por Greg Rogers.
  • @pgreze imaginați-vă cazul în care n=-1000 și m=3, răspunsul corect ar fi 2, dar în formula ta răspunsul este tot negativ. –  > Por Felipe Nardi Batista.
codepleb

De la Java 8 se poate utiliza funcția Math.floorMod() metoda:

Math.floorMod(-1, 2); //== 1

Notă: Dacă valoarea modulo (aici 2) este negativă, toate valorile de ieșire vor fi și ele negative. 🙂

Source: https://stackoverflow.com/a/25830153/2311557

amit

Dacă aveți nevoie de n % m atunci:

int i = (n < 0) ? (m - (abs(n) % m) ) %m : (n % m);

explicații matematice:

n = -1 * abs(n)
-> n % m = (-1 * abs(n) ) % m
-> (-1 * (abs(n) % m) ) % m
-> m - (abs(n) % m))

Comentarii

  • Această expresie nu a funcționat pentru mine. Pentru valori negative obțineam valori între 1:m în loc de 0:m-1, cum era de așteptat, ca în cazul în care n este pozitiv. Soluția de la andrewmu a funcționat conform așteptărilor. –  > Por Cachapa.
Dico
if b > 0:
    int mod = (mod = a % b) < 0 ? a + b : a;

Nu folosește % operator de două ori.

Comentarii

  • Cum se compară viteza acesteia cu cea a versiunii cu doi operatori %? –  > Por Christian.
  • Aceasta este o întrebare bună. Eu efectuez o mulțime de optimizări premature. Presupun că economisește câteva cicluri CPU. –  > Por Dico.
  • @Dice : Dacă argumentezi bine că această soluție este mai bună decât cea acceptată în prezent, ar fi valoros pentru cei care răsfoiesc această întrebare. –  > Por Christian.
  • Dacă o if este mai rapidă decât un % depinde de procesorul dvs. și de datele pe care i le furnizați, din cauza predicției de ramificare…ifs sunt mai rapide dacă starea are un tipar previzibil. –  > Por Vitruvius.
  • Aceasta este aproape sigur mai lentă pentru că are o ramificare, cu excepția cazului în care știți că datele de intrare vor fi în cea mai mare parte pozitive. Dacă este aleatorie, atunci penalizarea de predicție a ramurii va costa mai multe cicluri de ceas decât un calcul suplimentar al restului pe majoritatea procesoarelor. Sau, dacă doriți să adăugați condiționat o valoare în funcție de faptul că un int este negativ sau nu, încercați (maybeNegative >> 31) ^ thingToMaybeAdd + thingToAddTo –  > Por Scott Carey.
Neil

Dacă modulul este o putere de 2, atunci puteți folosi o mască de biți:

int i = -1 & ~-2; // -1 MOD 2 is 1

Prin comparație, limbajul Pascal oferă doi operatori; REM ia semnul numitorului (x REM y este x - (x DIV y) * y unde x DIV y este TRUNC(x / y)), iar MOD necesită un numitor pozitiv și returnează un rezultat pozitiv.

Tags:, ,