Pregunta

Así que tengo una función que se ve algo como esto:

float function(){
    float x = SomeValue;
    return x / SomeOtherValue;
}

En algún momento, esta función se desborda y se devuelve realmente un gran valor negativo.Para tratar de localizar exactamente donde estaba pasando esto, he añadido un cout declaración, por lo que la función se veía así:

float function(){
    float x = SomeValue;
    cout << x;
    return x / SomeOtherValue;
}

¡y funcionó!Por supuesto, he resuelto el problema por completo mediante el uso de un doble.Pero soy curioso en cuanto a por qué la función ha funcionado correctamente, cuando me couted ella.Es típico, o podría haber un error en alguna otra parte de que me estoy perdiendo?

(Si te sirve de ayuda, el valor almacenado en el flotador es sólo un valor entero, y no especialmente grande.Acabo de poner en un flotador para evitar la proyección.)

¿Fue útil?

Solución

Bienvenido al maravilloso mundo de punto flotante.La respuesta que obtenga dependerá, probablemente, la de punto flotante modelo de compilar el código con.

Esto ocurre debido a la diferencia entre la especificación IEEE y el hardware se ejecuta el código en el.Su CPU es probable que tenga 80 bits de punto flotante registros que utilizar para contener 32 bits en coma flotante valor.Esto significa que hay mucha más precisión, mientras que el valor se mantiene en un registro de cuando es forzado a una dirección de memoria (también conocido como "homing" el registro").

Cuando se pasa el valor a cout el compilador tenía que escribir el punto flotante a la memoria, y esto se traduce en una pérdida de precisión y un comportamiento interesante WRT desbordamiento de los casos.

Consulte la documentación de MSDN en VC++ de punto flotante de interruptores.Usted podría tratar de compilar con /fp:la estricta y ver qué pasa.

Otros consejos

Impresión de un valor a cout no debe cambiar el valor del parámetro en cualquier forma.

Sin embargo, he visto un comportamiento similar, añadiendo la depuración de las declaraciones de hace un cambio en el valor.En esos casos, y probablemente esta así mi conjetura es que las declaraciones adicionales que estaban causando el compilador optimizador se comportan de manera diferente, de modo de generar código diferente para su función.

La adición de la cout declaración significa que el vaue de x se utiliza directamente.Sin ella, el optimizador puede quitar la variable, por lo que cambiar el orden de los cálculos, y por lo tanto cambiar la respuesta.

Como un aparte, siempre es una buena idea para declarar inmutable variables mediante const:

float function(){
    const float x = SomeValue;
    cout << x;
    return x / SomeOtherValue;
}

Entre otras cosas esto evitará que sin querer pasar variables a las funciones que puede modificar a través de la no-const las referencias.

cout hace una referencia a la variable, que a menudo hará que el compilador de la fuerza que se derrame a la pila.

Porque es un flotador, este probable causa de su valor truncado desde el double o long double representación que normalmente tendría.

Llamar a cualquier función (no en línea) que toma un puntero o referencia de x debe terminar causando el mismo comportamiento, pero si el compilador más tarde se vuelve más inteligente y aprende a en línea, vas a ser igual de jodido :)

No creo que el cout tiene ningún efecto sobre la variable, el problema tendría que ser en algún lugar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top