x10 valor siguiente separadores que literal entero cuál c++ gcc precision literals

valor - ¿Hay un sufijo literal de punto flotante en C++ para hacer una precisión doble de número?



¿cuál es el valor del siguiente literal? 018 (4)

Como dijo Mark, el estándar dice que es un doble a menos que sea seguido por una f.

Hay buenas razones detrás del estándar y el uso de indicadores de compilación para sortearlo por conveniencia es una mala práctica.

Entonces, el enfoque correcto sería:

  1. Eliminar la bandera del compilador
  2. Corrija todas las advertencias sobre la pérdida de precisión al almacenar valores dobles en variables de punto flotante (agregue todos los sufijos f)
  3. Cuando necesites doble, omite el sufijo f.

Probablemente no sea la respuesta que estaba buscando, pero es el enfoque que debe utilizar si le importa la longevidad de su código base.

Actualmente estoy trabajando en un proyecto de C ++ que hace cálculos numéricos. La gran mayoría del código utiliza valores de punto flotante de precisión simple y funciona perfectamente bien con eso. Debido a esto, uso banderas de compilador para hacer literales básicos de punto flotante con una precisión única en lugar de la precisión doble, que es la predeterminada. Encuentro que esto hace que las expresiones sean más fáciles de leer y no tengo que preocuparme por olvidar una ''f'' en algún lugar. Sin embargo, de vez en cuando necesito la precisión adicional que ofrecen los cálculos de doble precisión y mi pregunta es cómo puedo obtener un literal de doble precisión en tal expresión. En todas las formas en que lo he intentado, primero almacene el valor en una sola variable de precisión y el valor truncado se convierte en un valor de doble precisión. No es lo que quiero.

Algunas formas que he probado hasta ahora se dan a continuación.

#include <iostream> int main() { std::cout << sizeof(1.0E200) << std::endl; std::cout << 1.0E200 << std::endl; std::cout << sizeof(1.0E200L) << std::endl; std::cout << 1.0E200L << std::endl; std::cout << sizeof(double(1.0E200)) << std::endl; std::cout << double(1.0E200) << std::endl; std::cout << sizeof(static_cast<double>(1.0E200)) << std::endl; std::cout << static_cast<double>(1.0E200) << std::endl; return 0; }

Una carrera con constantes de precisión simple da los siguientes resultados.

~/path$ g++ test.cpp -fsingle-precision-constant && ./a.out test.cpp:6:3: warning: floating constant exceeds range of ‘float’ [-Woverflow] test.cpp:7:3: warning: floating constant exceeds range of ‘float’ [-Woverflow] test.cpp:12:3: warning: floating constant exceeds range of ‘float’ [-Woverflow] test.cpp:13:3: warning: floating constant exceeds range of ‘float’ [-Woverflow] test.cpp:15:3: warning: floating constant exceeds range of ‘float’ [-Woverflow] test.cpp:16:3: warning: floating constant exceeds range of ‘float’ [-Woverflow] 4 inf 16 1e+200 8 inf 8 inf

Tengo entendido que los 8 bytes proporcionados por los dos últimos casos deberían ser suficientes para contener 1.0E200, una teoría respaldada por la siguiente salida, donde el mismo programa se compila sin la constante de precisión simple.

~/path$ g++ test.cpp && ./a.out 8 1e+200 16 1e+200 8 1e+200 8 1e+200

Una posible solución sugerida por los ejemplos anteriores es usar literales de punto flotante de precisión cuádruple en todos los lugares en los que originalmente pensé usar precisión doble, y convertirlos en precisión doble cuando sea necesario en bibliotecas y similares. Sin embargo, esto se siente un poco inútil.

¿Que más puedo hacer?


No puedes definir tu propio sufijo, pero tal vez una macro como

#define D(x) (double(x##L))

trabajaría para ti. El compilador debería emitir una constante doble y parece que aparece con -O2 en mi sistema.


Si lees 2.13.3 / 1 verás:

El tipo de un literal flotante es doble a menos que se especifique explícitamente con un sufijo. Los sufijos f y F especifican float, los sufijos l y L especifican long double.

En otras palabras, no hay un sufijo para especificar el double para una constante de punto flotante literal si cambia el valor predeterminado a float . Desafortunadamente, en este caso no puedes tener lo mejor de ambos mundos.


Si puede pagar GCC 4.7 o Clang 3.1, use un literal definido por el usuario:

double operator "" _d(long double v) { return v; }

Uso:

std::cout << sizeof(1.0E200_d) << std::endl; std::cout << 1.0E200_d << std::endl;

Resultado:

8 1e+200