2012-03-19 15 views
10

Esto comporta como querían:¿Por qué es (1/2) * x diferente de 0.5 * x?

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

pero esto no significa:

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

r es un 2-D vector.

Sólo pensé en una posibilidad. ¿Es porque (1/2) se considera int y (1/2) == 0?

+55

¿Por qué se vota por un problema básico sobre los tipos enteros y flotantes? – tbert

+29

No solo básico, pero el OP ya tenía la respuesta pero no la probó. Los votos son tan aleatorios en SO ... –

+4

Obtiene ojos extra porque es una "pregunta candente" en StackExchange. Ojos extra = votos adicionales. –

Respuesta

58

¿Es porque (1/2) se considera un int y (1/2) == 0?

Sí, estos dos literales son de tipo int, por lo tanto, el resultado será de tipo int, y ese resultado es 0.

su lugar, hacer uno de esos literales a float o double y' ll terminar con el resultado de punto flotante de 0.5, es decir:

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

Debido 1.0 es de tipo double, int 2 se promocionará a double y el resultado será double.

14

escribir este lugar:

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

1/2 es una división entera y el resultado es 0.

1/2.0 es una división de punto flotante (con double valores después de las conversiones aritméticas habituales) y su resultado es 0.5.

5

Porque 1/2 es int/int división. Eso significa que cualquiera que sea el resultado tendrá algo después de que se eliminó el punto decimal (truncado). Así 1/2 = 0,5 = 0.

Normalmente Siempre escribo el primer número de double: 1.0/2 ... ..

Si realiza el primer número de un double entonces todo cálculo restante se realiza en un solo double.

+0

No tiene que ser * el primer número *, solo uno de ellos al menos. – Marlon

+0

Simplemente haga un hábito de usar el primer número como flotador, entonces no se encontrará con sorpresas. Otra buena costumbre es comenzar con 1.0 * .... – AgA

+2

Tenga en cuenta que en '2.0 * x + (7/5)', el primer número es 'doble' y el problema del OP aún está presente. –

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

es equivalente a:

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

y no:

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

Debido a la pérdida de la parte decimal cuando el resultado temporal del medio se almacena en una variable int.

Como pauta cada vez que hay una división y hay una posibilidad de que la respuesta es un número real, no utilice int o hacer uno de los operandos float o double o uso fundido.

1

Puede escribir 1.0/2.0 en su lugar. 1/2 muestra este comportamiento porque tanto el denominador como el acto del numerador son de un tipo entero y una variable de un tipo entero dividido por otra variable de un tipo entero siempre se trunca en un entero.

0

No puedo merecer o desmerecer el estándar de la pregunta, pero este parece un problema muy crítico para mí. Suponemos que el compilador nos lavará la ropa todo el tiempo, pero that is not true algunas veces.

¿Hay alguna forma de evitar esta situación?

Possibly

O

que es más importante saber el monstruo (C, C++) ya que la mayoría de las personas señalan por encima de

Me gustaría saber si hay otras maneras de rastrear estos " "truncamiento" en el momento de la compilación

+0

¿Qué le parece saber el idioma y probar su código? –

+0

@JonathonReinhart no hay argumento sobre eso :) Pero en mi opinión es sobreingeniería e inesperado (en sentido matemático). Aprende algo de segundo o tercer grado en adelante y de repente algunos ingenieros compiladores deciden cambiar la lógica matemática ... y las computadoras son para humanos, no viceversa. Los hábitos humanos son difíciles de cambiar. Solo una humilde opinión :) – sakhunzai

Cuestiones relacionadas