2015-01-12 21 views
5

moltiplicando un set di int e convertendo il risultato in un lungo ottengo una risposta diversa rispetto a quando moltiplico un set di doppi e converto il risultato in un lungo. es .:Moltiplicazione in C# errore

int a = 5; 
int b = 5; 
int c = 7; 
int d = 6; 
int ee = 6; 
int f = 8; 
int g = 9; 
int h = 6; 
int i = 6; 
int j = 4; 
int k = 8; 
int l = 9; 
int m = 5; 
long x = a * b * c * d * ee * f * g * h * i * j * k * l * m; 

double aa = 5; 
double ab = 5; 
double ac = 7; 
double ad = 6; 
double aee = 6; 
double af = 8; 
double ag = 9; 
double ah = 6; 
double ai = 6; 
double aj = 4; 
double ak = 8; 
double al = 9; 
double am = 5; 
long y = (long)(aa * ab * ac * ad * aee * af * ag * ah * ai * aj * ak * al * am); 

Qualcuno può dirmi perché questo accade? Grazie

+2

perché '' long'' e '' double' 'sono cose diverse –

+2

Double e float __cannot__ contengono un numero qualsiasi con precisione del 100%, a meno che non sia una potenza di 2. Invece tengono solo __approximations__ .. Per questo motivo abbiamo il decimale – TaW

+1

Ti consiglio di abilitare i controlli di overflow nelle impostazioni del progetto (a almeno per la build di debug). – CodesInChaos

risposta

13

hai un overflow intero, dal momento che ogni volta che si moltiplica due int avete int: questo viene interpretato come Int32 finora

a * b * c * d * ee * f * g * h * i * j * k * l * m 

e solo rispetto convertito in Int64 (long). Per correggere l'implementazione, dichiarare tutte le variabili inizialmente pari a long, ad es.

long a = 5; 
    long b = 5; // actually, not necessary, since a * b will be long, but safer 
    long c = 7; 
    ... 
    long m = 5; 

    long x = a * b * c * d * ee * f * g * h * i * j * k * l * m; 
+5

Non è nemmeno necessario renderli tutti 'lunghi'. Basta "forzare il calcolo" per farlo: 'long z = (long) a * b * c * d * ee * f * g * h * i * j * k * l * m;' – ChrFin

+2

@ChrFin: tu ' ho ragione, in questo caso, tecnicamente, * il primo argomento solo * deve essere di tipo 'Int64'; tuttavia, quando si confronta con l'overflow di interi, è più sicuro dire: "Devo lavorare con rappresentazioni a 64 bit" e trasformare tutti gli argomenti interi in 'Int64' –

+0

@DmitryBychenko: Grazie, ho pensato che fosse qualcosa del genere. – Ka0s

5

Questo probabilmente perché il risultato della moltiplicazione è troppo grande per contenere un Int32, tuttavia può essere considerato doppio.

essere un po 'più sguardo specifico a xey in esadecimale:

x = 0x000000007994b000
y = 0x000000057994b000

Un Int32 può contenere solo i valori esadecimali 8 inferiori. Questo è il motivo per cui x è il numero sbagliato. Gli 8 valori esadecimali più bassi sono corretti, ma la parte superiore è tagliata.

2

dò una breve ricerca ed eseguire alcuni test anche su script come bene e ho trovato i seguenti risultati, in formato script provo come,

<script> 
     var a = 5; 
     var b = 5; 
     var c = 7; 
     var d = 6; 
     var ee = 6; 
     var f = 8; 
     var g = 9; 
     var h = 6; 
     var i = 6; 
     var j = 4; 
     var k = 8; 
     var l = 9; 
     var m = 5; 
     var x = a * b * c * d * ee * f * g * h * i * j * k * l * m; 
     var y = eval(a * b * c * d * ee * f * g * h * i * j * k * l * m); 
     document.writeln("RESULT X : " + x); 
     document.write("<br>"); 
     document.writeln("RESULT Y : " + y); 
    </script> 

e il risultato è stato 23514624000 sia per x sia per , ma in C# come si tenta di moltiplicare tutti gli interi e nel risultato si forma un intero ma sappiamo anche che int.MAX = 2147483647 che è minore del risultato actuall, Quindi in risultato quando si assegna a long x= a * b * c * d * ee * f * g * h * i * j * k * l * m; tronca i valori originali, e in altri re Sult non lo è, se si desidera che lo stesso risultato in entrambi è possibile utilizzare codice seguente,

int a = 5; 
int b = 5; 
int c = 7; 
int d = 6; 
int ee = 6; 
int f = 8; 
int g = 9; 
int h = 6; 
int i = 6; 
int j = 4; 
int k = 8; 
int l = 9; 
int m = 5; 
long x = (long)a * b * c * d * ee * f * g * h * i * j * k * l * m; 

double aa = 5; 
double ab = 5; 
double ac = 7; 
double ad = 6; 
double aee = 6; 
double af = 8; 
double ag = 9; 
double ah = 6; 
double ai = 6; 
double aj = 4; 
double ak = 8; 
double al = 9; 
double am = 5; 
long y = (long)(aa * ab * ac * ad * aee * af * ag * ah * ai * aj * ak * al * am); 
Console.WriteLine(x); 
Console.WriteLine(y); 
Console.ReadKey(); 

Ora si otterrà lo stesso risultato cioè