Sto sbagliando il modulo? Perché in Java -13 % 64
si suppone che valuti -13
ma ottengo 51
.
%
è un operatore resto.
Sto sbagliando il modulo? Perché in Java -13 % 64
si suppone che valuti -13
ma ottengo 51
.
%
è un operatore resto.
Risposte:
Entrambe le definizioni di modulo dei numeri negativi sono in uso: alcune lingue usano una definizione e altre l'altra.
Se vuoi ottenere un numero negativo per input negativi, puoi usare questo:
int r = x % n;
if (r > 0 && x < 0)
{
r -= n;
}
Allo stesso modo se stai usando una lingua che restituisce un numero negativo su un input negativo e preferiresti positivo:
int r = x % n;
if (r < 0)
{
r += n;
}
x % y
, A) se x
è negativo il resto è negativo, cioè x % y == -(-x % y)
. B) il segno di y
non ha effetto, ad esempiox % y == x % -y
Poiché "matematicamente" entrambi sono corretti:
-13 % 64 = -13 (on modulus 64)
-13 % 64 = 51 (on modulus 64)
Una delle opzioni doveva essere scelta dagli sviluppatori di linguaggi Java e hanno scelto:
il segno del risultato è uguale al segno del dividendo.
Lo dice nelle specifiche Java:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.3
-13 % 64 = 51
quando me l'aspettavo -13
?".
int result = (-5) % 3;
dà -2. int result = (-3) % 5;
dà -3. In generale, int result = (-a) % b;
dà la risposta giusta quando | -a | > b. Per ottenere il risultato corretto quando | -a | <b dovremmo racchiudere il divisore. int result = ((-a) % b) + b;
per a negativa o int result = (((-a) % b) + b) % b;
per a positiva o negativa
Il tuo risultato è sbagliato per Java. Fornisci un contesto su come ci sei arrivato (programma, implementazione e versione di Java).
Dal specifiche del linguaggio Java
15.17.3 Operatore rimanente%
[...]
L'operazione resto per operandi che sono numeri interi dopo la promozione numerica binaria (§5.6.2) produce un valore risultato tale che (a / b) * b + (a% b) è uguale a un.
15.17.2 Operatore Divisione /
[...]
divisione arrotonda verso 0.
Poiché / è arrotondato verso zero (risultando in zero), il risultato di% dovrebbe essere negativo in questo caso.
int result = (-5) % 3;
dà -2 int result = (-3) % 5;
dà -3 In generale, int result = (-a) % b;
dà la risposta giusta quando | -a | > b Per ottenere il risultato corretto quando | -a | <b dovremmo racchiudere il divisore. int result = ((-a) % b) + b;
per a negativo o int result = (((-a) % b) + b) % b;
per positivo o negativo a.
(-3) % 5
il risultato corretto secondo la definizione è -3
, e una corretta implementazione di Java dovrebbe produrre quel risultato.
(-3)%5
infatti dà -3
, e se vogliamo il resto positivo dovremmo aggiungere 5 ad esso, e quindi il risultato sarà2
Puoi usare
(x % n) - (x < 0 ? n : 0);
((x % k) + k) % k
. (Anche se il tuo è probabilmente più leggibile.)
[0, sign(divisor) * divisor)
anziché [0, sign(dividend) * divisor)
.
La tua risposta è in wikipedia: operazione modulo
Dice che in Java il segno sull'operazione modulo è lo stesso di quello del dividendo. e poiché stiamo parlando del resto dell'operazione di divisione va benissimo, che nel tuo caso ritorni -13, poiché -13/64 = 0. -13-0 = -13.
EDIT: Scusa, ho capito male la tua domanda ... Hai ragione, java dovrebbe dare -13. Potete fornire più codice circostante?
L'aritmetica del modulo con operandi negativi è definita dal progettista del linguaggio, che potrebbe lasciarla all'implementazione del linguaggio, che potrebbe rimandare la definizione all'architettura della CPU.
Non sono riuscito a trovare una definizione del linguaggio Java.
Grazie Ishtar, Java Language Specification for the Remainder Operator% afferma che il segno del risultato è lo stesso del segno del numeratore.
x = x + m = x - m
in modulo m
.
quindi -13 = -13 + 64
in modulo 64
e -13 = 51
in modulo 64
.
supponiamo Z = X * d + r
, se 0 < r < X
poi in divisione Z/X
chiamiamo r
resto.
Z % X
restituisce il resto di Z/X
.
La funzione mod è definita come la quantità di cui un numero supera il multiplo intero più grande del divisore che non è maggiore di quel numero. Quindi nel tuo caso di
-13 % 64
il multiplo intero più grande di 64 che non supera -13 è -64. Ora, quando sottrai -13 da -64 è uguale a 51-13 - (-64) = -13 + 64 = 51
Nella mia versione di Java JDK 1.8.0_05 -13% 64 = -13
potresti provare -13- (int (-13/64)) in altre parole eseguire il cast di divisione su un numero intero per eliminare la parte frazionaria quindi sottrarre dal numeratore Quindi numeratore- (int (numeratore / denominatore)) dovrebbe dare il corretto resto e segno
Nelle ultime versioni di Java ottieni -13%64 = -13
. La risposta avrà sempre segno del numeratore.
Secondo la sezione 15.17.3 del JLS, "L'operazione resto per gli operandi che sono numeri interi dopo la promozione numerica binaria produce un valore di risultato tale che (a / b) * b + (a% b) è uguale ad a. Questa identità vale anche nel caso speciale in cui il dividendo è l'intero negativo di grandezza maggiore possibile per il suo tipo e il divisore è -1 (il resto è 0). "
Spero che aiuti.
Non credo che Java restituisca 51 in questo caso. Sto eseguendo Java 8 su un Mac e ottengo:
-13 % 64 = -13
Programma:
public class Test {
public static void main(String[] args) {
int i = -13;
int j = 64;
System.out.println(i % j);
}
}