Hacer que los literales de punto flotante de C floten (en lugar del doble)

5 minutos de lectura

Hacer que los literales de punto flotante de C floten
Zeus

Es bien sabido que en C, los literales de punto flotante (p. ej. 1.23) tiene tipo double. Como consecuencia, cualquier cálculo que los involucre se promueve al doble.

Estoy trabajando en un sistema integrado en tiempo real que tiene una unidad de punto flotante que solo admite precisión simple (float) números. Todas mis variables son float, y esta precisión es suficiente. No necesito (ni puedo permitirme) double en absoluto. Pero cada vez que algo como

if (x < 2.5) ...

está escrito, ocurre el desastre: la desaceleración puede ser de hasta dos órdenes de magnitud. Por supuesto, la respuesta directa es escribir

if (x < 2.5f) ...

pero esto es tan fácil de pasar por alto (y difícil de detectar hasta que es demasiado tarde), especialmente cuando un valor de ‘configuración’ es #define‘d en un archivo separado por un desarrollador menos disciplinado (o simplemente nuevo).

Entonces, ¿hay alguna manera de obligar al compilador a tratar todos los literales (punto flotante) como flotantes, como si tuvieran el sufijo f? Incluso si va en contra de las especificaciones, no me importa. ¿O alguna otra solución? El compilador es gcc, por cierto.

  • hay -Wdouble-promotion, que al menos te dará advertencias. Combinado con -Wfloat-conversion debe dar bastante buena cobertura.

    – Brett Hale

    28 de agosto de 2015 a las 8:47


  • Esto no responde directamente a su pregunta, pero no sería tan difícil escribir un script para simplemente insertar cualquier faltante. fs de literales FP.

    – Xophmeister

    28 de agosto de 2015 a las 8:47

  • ¿Ayuda esto: stackoverflow.com/questions/24688911/… ?

    – Raúl Tripathi

    28 de agosto de 2015 a las 8:49

  • Algunos compiladores para sistemas integrados asignan doble a flotante y solo habilitan doble precisión con una opción. No se si hay algo similar en GCC

    – phuclv

    28 de agosto de 2015 a las 8:56

  • @BrettHale Ese comentario es digno de ser una respuesta adecuada. Creo que recibir advertencias en este caso sería más productivo que alguna otra opción del compilador que permite al programador escribir código que no es compatible con el estándar.

    – usuario694733

    28 de agosto de 2015 a las 11:36

-fsingle-precision-constant Se puede usar la bandera. Hace que las constantes de coma flotante se carguen con precisión simple incluso cuando esto no es exacto.

Nota: esto también utilizará constantes de precisión simple en operaciones con variables de doble precisión.

  • ¡Gracias! No conocía esta bandera. Esto responde perfectamente a mi pregunta, aunque, como sugirieron otros, quizás sería más prudente generar advertencias.

    – Zeus

    31 de agosto de 2015 a las 2:35

  • @Zeus ¡Me alegro de que haya ayudado! 🙂

    – ameyCU

    31 de agosto de 2015 a las 6:52

  • ¡Usaría esta opción sabiamente! Considere un nuevo desarrollador, simplemente escribiendo x < 2.5, todo estará bien. Es probable que se pierda esa opción específica del compilador que le salva la vida :-). Cuando recibe advertencias en su lugar (con -Wdouble-promotion, -Wfloat-conversion), y usas -Werror que convierte todas las advertencias en errores, es posible que no verifique directamente el código y que se pregunte y aprenda. Pero solo por la calidad del lanzamiento, es posible que desee jugar de forma segura y compilarlo con la opción específica (-fsingle-precision-constant). Tenga en cuenta que esto es solo un comentario.

    – Matemáticas

    4 de septiembre de 2015 a las 7:47


1647549498 763 Hacer que los literales de punto flotante de C floten
Brett Hale

Utilice advertencias en su lugar: -Wdouble-promotion advierte sobre implícito flotar para duplicar la promoción, como en su ejemplo. -Wfloat-conversion advertirá sobre casos en los que aún puede estar asignando dobles a flotantes.

Esta es una mejor solución que simplemente forzar valores dobles al valor flotante más cercano. Su código de punto flotante sigue siendo compatible y no recibirá sorpresas desagradables si un valor doble tiene un valor positivo, digamos, menos de FLT_DENORM_MIN (suponiendo IEEE-754) o superior a FLT_MAX.

  • Tienes razón en general, por supuesto. Sin embargo, en mis circunstancias específicas -fsingle-precision-constant funciona mejor Primero, mi versión de GCC (4.4.7) simplemente no tiene ninguna de estas opciones. En segundo lugar, no tengo constantes difíciles (aparte de NaN), y todos los cálculos deben ser float de todos modos (este es el punto). Finalmente, la biblioteca de chips suministrada genera tantas advertencias (¡la mayoría de ellas explícitas!) que las útiles a menudo quedan enterradas en la pila… Y, como dije, no me preocupa mucho el cumplimiento estricto en este caso.

    – Zeus

    31 de agosto de 2015 a las 2:32

  • Yo también creo que es peligroso simplemente ocultar un problema que está en su código fuente usando un interruptor de comando. Solo considere que su código podría ser usado por otra persona dentro de cinco años usando una nueva versión del compilador, tal vez sin ese cambio tan bueno. Es preferible solucionar los problemas en el código fuente que ocultarlos. Y sobre todas estas advertencias… al compilar para producción, las advertencias deben considerarse errores. -Error 🙂

    – Chrissi

    2 de septiembre de 2015 a las 6:26

  • no hay nada de inteligente en obligarte a escribir f al final de cada número literal,

    – 12Me21

    3 de marzo de 2021 a las 3:39

  • @ 12Me21: mire la salida asm de: float fn (float x) { return (x * 1.2); } contra (1.2f) – la expresión se fuerza a ser evaluada como un doble y luego se vuelve a convertir en un flotante. No es una cuestión de ser ‘inteligente’.

    – Brett Hale

    3 de marzo de 2021 a las 9:25

  • oh, solo quise decir, siento que -fsingle-precision-constant es una mejor solución aquí. mismo resultado con menos esfuerzo.

    – 12Me21

    4 de marzo de 2021 a las 5:07

Puede convertir las constantes definidas en (float) dondequiera que se utilicen, el optimizador debería hacer su trabajo. Esta es una solución portátil.

#define LIMIT 2.5

if (x < (float)LIMIT) ...

  • O inclúyalos en la definición, como en #define foo ((float) 1.234)

    – Conejo curioso

    3 sep 2015 a las 14:10


  • @CuriousRabbit: eso no aborda el problema de “un desarrollador menos disciplinado (o simplemente nuevo)”.

    – Yves Daoust

    3 de septiembre de 2015 a las 14:19

los -Wunsuffixed-float-constants flag también podría usarse, tal vez combinado con algunas de las otras opciones en la respuesta aceptada anterior. Sin embargo, esto probablemente no detectará constantes sin sufijo en los encabezados del sistema. necesitaría usar -Wsystem-headers para atraparlos también. Podría generar muchas advertencias…

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad