2012-06-07 20 views
12

Cuando un doble tiene un valor entero 'exacta', así:Cuando un doble con un valor entero se convierte en un número entero, ¿se garantiza que lo haga "correctamente"?

double x = 1.0; 
double y = 123123; 
double z = -4.000000; 

¿Está garantizado que va a redondear adecuadamente a 1, 123123, y -4 cuando se convierte a través de un tipo entero (int) x , (int) y, (int) z? (Y no truncar a 0, 123122 o -5 b/c de rareza de coma flotante). Pregunto b/c de acuerdo con this page (que es sobre fp's en lua, un lenguaje que solo se dobla como su tipo numérico de forma predeterminada), habla sobre cómo las operaciones de enteros con dobles son exactas de acuerdo con IEEE 754, pero no estoy seguro si, cuando llamo a C-funciones con parámetros de tipo entero, tengo que preocuparme de redondear los dobles manualmente, o se tiene cuidado cuando los dobles tienen valores enteros exactos.

+0

Debe aclarar algunos elementos aquí a) haciendo doble te refieres a 8 bytes o 4 bytes yb) por correcto, ¿quieres decir que la ronda va hacia cero? – JaredPar

+0

Posible duplicado: http://stackoverflow.com/questions/9154687/validity-of-checking-exact-value-of-preset-double – Ruben

+1

No se está produciendo un "redondeo". El elenco realiza el truncamiento. –

Respuesta

9

Sí, si el valor entero cabe en un int.

A double podría representar valores enteros que están fuera del rango para su tipo int. Por ejemplo, 123123.0 no se puede convertir a int si su tipo int tiene solo 16 bits.

Tampoco se garantiza que un double pueda representar cada valor que un tipo particular pueda representar. IEEE 754 usa algo así como 52 o 53 bits para la mantisa. Si su long tiene 64 bits, la conversión de un muy grande long a double y viceversa podría no dar el mismo valor.

+0

La norma proporciona esa garantía para valores cuya parte integral se puede representar en el tipo de objetivo en 6.3.1.4: "Cuando un valor finito de flotación real type se convierte a un tipo entero distinto de _Bool, la parte fraccionaria se descarta (es decir, el valor se trunca hacia cero). Si el valor de la parte integral no se puede representar mediante el tipo entero, el comportamiento no se define. " –

+0

@DanielFischer: Gracias por la referencia. He actualizado la respuesta. –

0

Sí, mantendrá el valor exacto que le da porque lo ingresa en el código. A veces, en los cálculos sería dió ,99999999999 por ejemplo, pero eso es debido al error en el cálculo de dobles no su capacidad de almacenamiento

1

Será hacerlo correctamente, si realmente es cierto entero, que es posible estar seguro de en algunos contextos. Pero si el valor es el resultado de cálculos previos de punto flotante, no podría saberlo fácilmente.

¿Por qué no se calcula explícitamente el valor con la función floor(), como en long value = floor(x + 0.5). O, mejor aún, use la función modf() para inspeccionar un valor entero.

+0

Si sabe que el valor es un número entero, entonces no hay ventaja en el uso de la función floor() vs.un molde (excepto cuando el idioma no tiene un tipo entero, por ejemplo, Lua, JS). – finnw

3

Como dijo Daniel Fischer, si el valor de la parte entera del doble (en su caso, el doble exactamente) es representable en el tipo al que está convirtiendo, el resultado es exacto. Si el valor está fuera del rango del tipo de destino, el comportamiento no está definido. "Indefinido" significa que la norma permite cualquier comportamiento: puede obtener el número representable más cercano, puede obtener cero, puede obtener una excepción o la computadora puede explotar. (Nota: Si bien el estándar C permite que su computadora explote, o incluso destruya el universo, es probable que las especificaciones del fabricante impongan un límite más estricto al comportamiento).

+2

A pesar de mi ligereza sobre el comportamiento indefinido, quiero señalar que tiene serias consecuencias. Suponga que supone que algunos resultados serán incorrectos porque están fuera de los límites, pero los detectará y descartará después de la conversión. Una consecuencia no deseada del optimizador del compilador es que, si puede demostrar que su código obtiene un comportamiento indefinido, puede optimizar su código y todo lo que lo llame, reemplazándolo con salidas deliberadas del programa o cualquier otro código. –

Cuestiones relacionadas