2010-11-16 22 views
10

Estoy tratando de calcular algunos números en una aplicación de iPhone.Objective-C Integer Aritmética

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

que sería de esperar o sea 100 (que es milisegundos) en este ejemplo, pero es igual a 0 como se muestra por NSLog (@ "% d", o).

Esto también es igual a 0.

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

Esto equivale a 250.000, lo que es matemática recta de izquierda a derecha.

¿Qué está volando por mi cabeza aquí?

Gracias,
Nick

+3

Consulte [C problema: el resultado de la división siempre es cero ] (http://stackoverflow.com/questions/2345902/c-problem-division-result-is- all-cero-cero). –

Respuesta

19

En Objective-C / realiza la división de enteros en argumentos enteros, por lo que 4/5 se trunca a 0, 3/2 se trunca a 1, y así sucesivamente. Es probable que desee enviar algunos de sus números a formularios de coma flotante antes de realizar la división.

También estamos quedando a problemas con precedencia. En la expresión

60/(i * 50) * 1000 

el término dentro del paréntesis se calcula primero, por lo que 60 se divide por 600 que produce el resultado 0. En

60/i * 50 * 1000 

la primera operación es dividir 60 por 12 que da el resultado 5 y luego las multiplicaciones se llevan a cabo.

+3

C también, por supuesto. La aritmética en Objective-C es idéntica a la aritmética en C. :) –

+6

Estrictamente hablando, el resultado no se redondea, sino que se trunca. – Dima

+1

Bueno, el truncamiento es una forma de redondeo (hacia cero) así que ... sí. –

4

Un entero dividido por un número entero es un número entero.

así que 60/600 no es 0.1, es 0.

Emitir (o declarar) algunas cosas como float en su lugar.

+1

Fundir o introducir una conversión implícita a 'float' o' double' es ** not ** la forma de evaluar expresiones enteras. En los sistemas sin coma flotante IEEE, podría dar resultados muy falsos (C casi no requiere requisitos sobre la calidad de la implementación de coma flotante) e incluso con coma flotante IEEE, puede obtener errores por pérdida de precisión con números enteros demasiado grandes para caber en el tipo de punto flotante utilizado. La solución correcta al problema de OP es simplemente simplificar algebraicamente la expresión. –

1

Está haciendo cálculos enteros. 60/(12 * 50) es 0,1, trunca a 0.

En caso de trabajar si se fuerza coma flotante y luego arrojado de nuevo a un entero.

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

Probablemente no sea realmente necesario hacer que todo sea doble.

+1

Lanzar o introducir una conversión implícita a 'float' o' double' es ** no ** la forma de evaluar expresiones enteras. Vea mi comentario sobre la respuesta de Dave. –

0

Por orden de precedencia, la operación de:

60/(12 * 50) 

se lleva a cabo antes de multiplicar por 1000.

Este valor es inferior a 1 y se convierte en una int, que trunca a 0. Y 0 veces cualquier cosa es 0.

Use float o primero multiplique por 1000 para asegurarse de que no termine con la propagación de 0 en sus cálculos.

0

Todas las operaciones en su expresión se realizan en aritmética entera, lo que significa que la parte fraccionaria de cada resultado intermedio se trunca. Esto significa que si divide un entero más pequeño por un entero más grande, siempre obtendrá 0.

Para obtener el resultado que desea, debe asegurarse de que las operaciones se realicen en un orden particular, o debe usar flotantes. Por ejemplo, el resultado de

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

debe ser o = 100.

3

Reemplazar:

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

con:

int o = 1200/i; 
+1

Quien sea el infractor, explíquese. A diferencia de las otras respuestas, esta respuesta da el resultado entero truncado exacto del cálculo, sin ningún caso de esquina debido al desbordamiento o la pérdida de precisión. Por lo que puedo decir, es la única respuesta correcta aquí. –

0

Creo que es necesario utilizar en lugar de flotar aquí En t. ¡Funcionará de la manera que quieras! Te dará respuesta en decimales también.

+0

Si bien 'float' funcionará, ¡eso no soluciona el malentendido que causó el problema en primer lugar! – Andrew