2010-11-16 12 views
10

Sto provando a calcolare alcuni numeri in un'applicazione iPhone.Objective-C Integer Arithmetic

int i = 12; 
int o = (60/(i * 50)) * 1000; 

mi aspetterei o di essere 100 (che è millisecondi) in questo esempio, ma è uguale a 0, come visualizzato dal NSLog (@ "% d", o).

Questo equivale anche 0.

int o = 60/(i * 50) * 1000; 

Ciò equivale a 250.000, che è diritto di matematica da sinistra a destra.

Cosa sta volando sopra la mia testa qui?

Grazie,
Nick

+3

Vedere [Problema C: il risultato della divisione è sempre zero ] (http://stackoverflow.com/questions/2345902/c-problem-division-result-is-always-zero). –

risposta

19

In Objective-C / esegue divisione intera su argomenti interi, quindi 4/5 viene troncato a 0, 3/2 viene troncato a 1, e così via. Probabilmente vuoi lanciare alcuni dei tuoi numeri su moduli a virgola mobile prima di eseguire la divisione.

Stai anche correndo verso problemi con precedenza. Nell'espressione

60/(i * 50) * 1000 

il termine tra parentesi viene calcolata per prima, quindi 60 è diviso per 600 che produce il risultato 0.

60/i * 50 * 1000 

la prima operazione consiste nel dividere 60 da 12 che dà il risultato 5 e poi le moltiplicazioni vengono eseguite.

+3

C, ovviamente. L'aritmetica in Objective-C è identica all'aritmetica in C. :) –

+6

In senso stretto, il risultato non è arrotondato, viene troncato. – Dima

+1

Bene, il troncamento è una forma di arrotondamento (verso zero) quindi ... sì. –

4

Un numero intero diviso per un intero è un numero intero.

quindi 60/600 non è 0.1, è 0.

Fondere (o dichiarare) alcune cose come float invece.

+1

La trasmissione o l'introduzione di una conversione implicita in 'float' o' double' è ** non ** il modo di valutare le espressioni intere. Sui sistemi senza IEEE in virgola mobile, potrebbe dare risultati fasulli (C non richiede quasi alcun requisito sulla qualità dell'implementazione in virgola mobile) e anche con IEEE in virgola mobile, è possibile ottenere errori dalla perdita di precisione con numeri interi troppo grandi per adattarsi al tipo a virgola mobile utilizzato. La soluzione corretta al problema dell'OP è semplicemente semplificare algebricamente l'espressione. –

1

Sta facendo matematica intera. 60/(12 * 50) è 0.1, troncato a 0.

Dovrebbe funzionare se si forza il punto mobile e quindi si esegue il cast di un numero intero.

int o = (int)(60.0/((double) i/50.0) * 1000.0; 

Probabilmente non è davvero necessario per rendere il tutto un doppio.

+1

Lanciare o introdurre una conversione implicita in 'float' o' double' è ** non ** il modo di valutare le espressioni intere. Vedi il mio commento sulla risposta di Dave. –

0

Con ordine di precedenza, l'operazione:

60/(12 * 50) 

viene eseguita prima di moltiplicare per 1000.

Questo valore è inferiore a 1 ed è convertito in uno, che lo tronca su 0. E 0 volte qualsiasi cosa è 0.

Utilizzare un float o prima moltiplicare per 1000 per assicurarsi di non finire con la propagazione di un 0 nei calcoli.

0

Tutte le operazioni nell'espressione vengono eseguite in aritmetica intera, nel senso che la parte frazionaria di ogni risultato intermedio viene troncata. Ciò significa che se dividi un intero più piccolo con un numero intero più grande otterrai sempre 0.

Per ottenere il risultato desiderato, devi assicurarti che le operazioni siano eseguite in un ordine particolare, oppure devi usare i float. Per esempio il risultato di

int o = (60.0/(i * 50.0)) * 1000.0; 

dovrebbe essere o = 100.

3

Sostituire:

int o = (60/(i * 50)) * 1000; 

con:

int o = 1200/i; 
+1

Chiunque sia il downvoter, spiegaci. A differenza delle altre risposte, questa risposta fornisce l'esatto risultato troncato-intero del calcolo, senza casi d'angolo dovuti a overflow o perdita di precisione. Per quanto posso dire è l'unica risposta corretta qui. –

0

Credo che è necessario utilizzare galleggiare qui invece di Int. Funzionerà nel modo desiderato! Vi darò risposta anche in decimali.

+0

Mentre 'float' funzionerà, ciò non risolve l'incomprensione che ha causato il problema in primo luogo! – Andrew