2010-07-26 8 views
6

en mi plataforma imprime esta 9223372036854775808.segura conversión de doble a entero sin signo de 64 bits

double x = 1e19; 
std::cout << static_cast<unsigned __int64>(x) << '\n'; 

Probé Boost.NumericConversion, pero dieron el mismo resultado.

Dividir x x en 2 partes iguales, y luego sumar las mitades convertidas da el resultado correcto. Pero necesito una solución genérica para usar en un código de plantilla.

Gracias de antemano.

EDITAR: Este problema aparece en Visual Studio 2008, pero no en MinGW. Lanzar 4.0e9 en unsigned long funciona bien.

Respuesta

10

Parece que funciona bien con gcc, pero es problemático en Visual Studio. Ver Microsoft's answer respecto a este tema:

Nuestro punto flotante a entero conversiones se realizan siempre en un entero de . En este caso particular de , usamos la instrucción FIST que genera 800 ... 00 como describió. Por lo tanto, no hay comportamiento definido para la conversión a unsigned valores enteros de 64 bits que son más grande que más grande de 64 bits con signo entero.

Por lo que sólo puede convertir los números en el rango entero de 64 bits: -9.223.372.036.854.775.808 a +9,223,372,036,854,775,807 (-2^63 ~ 2^63-1).

1

El comportamiento de su compilador no es conforme a C99, requiere que los valores positivos siempre se conviertan correctamente si es posible. Solo permite desviarse de eso para los valores negativos.

La operación en Saldo realiza cuando un valor de tipo entero es convertidos al tipo sin signo no necesita ser realiza cuando un valor de los bienes de tipo flotante se convierte a unsigned tipo. Por lo tanto, el rango de valores flotantes reales de portátiles es (-1, Utype_MAX + 1).

Para su código de plantilla, puede probar si su valor es mayor que static_cast<double>(UINT64_MAX/2) y hacer el trabajo de reparación que ya está haciendo. Si esto solo se aplica a las pruebas de constantes, esto debe optimizarse en los casos en que no sea relevante.

Cuestiones relacionadas