2009-05-25 24 views
10

Considerate questo:Perché l'operatore modulo non funziona per il doppio in C#?

double x,y; 
x =120.0; 
y = 0.05; 

double z= x % y; 

Ho provato questo e mi aspettavo che il risultato sia 0, ma è venuto fuori ,04,933333 millions.

Tuttavia,

x =120.0; 
y = 0.5; 
double z= x % y; 

ha infatti dato il giusto risultato di 0.

Cosa sta succedendo qui?

Ho provato Math.IEEERemainder(double, double) ma non restituisce neanche 0. Che cosa sta succedendo qui?

Inoltre, a parte, qual è il modo più appropriato per trovare il resto in C#?

+0

Sarebbe interessante sapere cosa stai cercando di ottenere. Usare il modulo con i numeri in virgola mobile non è mai una buona idea, come le risposte già affermano. – VVS

risposta

14

A causa del suo formato di archiviazione, double s non può memorizzare tutti i valori esattamente come è stato inserito o visualizzato. La rappresentazione umana dei numeri è solitamente in formato decimale, mentre gli double sono basati sul sistema duale.

In un double, 120 viene memorizzato in modo preciso perché è un valore intero. Ma non lo è il 0.05. Il doppio è approssimato al numero più vicino a 0.05 che può rappresentare. 0.5 è una potenza di 2 (1/2), quindi può essere memorizzata con precisione e non si ottiene un errore di arrotondamento.

Per avere tutti i numeri esattamente nello stesso modo in cui si inseriscono/visualizzano nel sistema decimale, utilizzare invece decimal.

decimal x, y; 
x = 120.0M; 
y = 0.05M; 

decimal z = x % y; // z is 0 
+0

Un 'double' è sempre un valore esatto. L'operazione che ha determinato il suo valore potrebbe essere inesatta. 'double a = 0.1;' -> 'a' ha un valore esatto che può leggermente differire rispetto a 0.1 matematico. 'double b = 0.125;' -> 'b' ha un valore esatto uguale a 0.125 matematico. Ancora una buona idea usare il 'decimale'. – chux

+2

"valore esatto che potrebbe leggermente differire" == inesatto. –

+0

Con numeri interi, il quoziente di 7 diviso per 3 è 2 e differisce dal quoziente matematico di 2.333 .... tuttavia gli interi sono considerati esatti. Allo stesso modo con FP, 7.0 diviso per 3.0 risulta in una risposta vicina, ma non uguale, al valore matematico di 2.333 ... In entrambi i casi, le operazioni non sono esattamente le stesse della matematica. In entrambi i casi i risultati sono esatti. – chux

9

Si potrebbe fare qualcosa di simile:

double a, b, r; 

a = 120; 
b = .05; 

r = a - Math.floor(a/b) * b; 

Questo dovrebbe aiutare;)

0

Modulo dovrebbe essere usato solo con numero intero Il resto proviene da una divisione euclidea. Con il doppio, puoi avere risultati imprevisti.

Vedi this article

+2

potresti tranquillamente usare modulo con decimali. –

1

Credo che se si è tentato la stessa cosa con decimal che avrebbe funzionato correttamente.