2012-03-19 32 views
10

Questo comporta come volevano:Perché è (1/2) * x diverso da 0,5 * x?

double t = r[1][0] * .5; 

ma questo non significa:

double t = ((1/2)*r[1][0]); 

r è un vettore 2-D.

Pensavo solo a una possibilità. È perché (1/2) è considerato un int e (1/2) == 0?

+55

Perché un problema di base relativo ai tipi intero vs float viene votato? – tbert

+29

Non solo di base, ma l'OP aveva già la risposta ma non l'ha provato. I voti sono così casuali in SO ... –

+4

Sta ricevendo molti occhi in più perché è una "domanda calda" in StackExchange. Bulbi oculari extra = voti extra. –

risposta

58

È perché (1/2) è considerato un valore int e (1/2) == 0?

Si, sia di quelle letterali sono di tipo int, quindi il risultato sarà di tipo int, e questo risultato è 0.

Invece, fare una di quelle letterali un float o double e si' ll finire con il risultato virgola mobile di 0.5, cioè:

double t = ((1.0/2)*r[1][0]);

Poiché 1.0 è di tipo double, il numero int verrà promosso a double e il risultato sarà un double.

14

scrittura invece:

double t = ((1/2.0)*r[1][0]); 

1/2 è una divisione intera ed il risultato è 0.

1/2.0 è una divisione in virgola mobile (con valori double dopo le normali conversioni aritmetiche) e il suo risultato è 0.5.

5

Perché 1/2 è int/int divisione. Ciò significa che qualunque sia il risultato avrà qualcosa dopo la rimozione del punto decimale (troncato). Così 1/2 = 0,5 = 0.

Normalmente scrivo sempre il primo numero in double: 1.0/2 ... ..

Se si effettua il primo numero di una double poi ogni calcolo restante è fatto in solo double.

+0

Non deve essere * il primo numero *, solo uno di essi almeno. – Marlon

+0

Basta prendere l'abitudine di usare il primo numero come float, quindi non ti imbatterai in sorprese. Un'altra buona abitudine è iniziare con 1.0 * .... – AgA

+2

Si noti che in '2.0 * x + (7/5)', il primo numero è un 'double' e il problema dell'OP è ancora presente. –

2
double t = r[1][0] * .5; 

è equivalente a:

double t = ((1/2f)*r[1][0]); 

e non:

double t = ((1/2)*r[1][0]); 

A causa della perdita di parte decimale quando il risultato temporaneo di 1/2 viene memorizzato in una variabile int.

Orientativamente ogni volta che c'è una divisione e v'è una possibilità di risposta essendo numero reale, non utilizzare int o fare uno degli operandi float o double oppure usa gettato.

1

È possibile invece scrivere 1.0/2.0. 1/2 mostra questo comportamento perché sia ​​il denominatore sia l'atto numeratore sono di un tipo intero e una variabile di un tipo intero diviso per un'altra variabile di un tipo intero viene sempre troncata su un numero intero.

0

Non posso meritare o demeritare lo standard della domanda, ma questo mi sembra un problema molto critico. Partiamo dal presupposto che il compilatore farà il bucato per noi tutto il tempo, ma a volte il numero that is not true.

C'è un modo per evitare questa situazione?

Possibly

O

Ancora più importante conoscere il mostro (C, C++) come la maggior parte delle persone sottolineano sopra

Vorrei sapere se ci sono altri modi per tracciare queste " "problemi di troncamento" al momento della compilazione

+0

Che ne dici di conoscere la lingua e testare il tuo codice? –

+0

@JonathonReinhart non ci sono argomenti a riguardo :) Ma a mio avviso la sua eccessiva ingegnerizzazione e inaspettata (in senso matematico). Si impara dal 2 ° o 3 ° grado in poi e improvvisamente alcuni ingegneri del compilatore decidono di cambiare la logica matematica ... ei computer sono per gli umani e non viceversa. Le abitudini umane sono difficili da cambiare. Solo un modesto parere :) – sakhunzai

Problemi correlati