web-dev-qa-db-fra.com

Faire flotter les littéraux en virgule flottante C (plutôt que doubler)

Il est bien connu qu'en C, les littéraux à virgule flottante (par exemple 1.23) ont le type double. En conséquence, tout calcul qui les implique est promu au double.

Je travaille sur un système embarqué en temps réel qui a une unité à virgule flottante qui prend en charge uniquement les nombres à simple précision (float). Toutes mes variables sont float, et cette précision est suffisante. Je n'ai pas besoin (ni ne peux me permettre) double du tout. Mais chaque fois que quelque chose comme

if (x < 2.5) ...

est écrit, une catastrophe se produit: le ralentissement peut aller jusqu'à deux ordres de grandeur. Bien sûr, la réponse directe est d'écrire

if (x < 2.5f) ...

mais c'est tellement facile à manquer (et difficile à détecter jusqu'à trop tard), surtout quand une valeur de "configuration" est #define 'd dans un fichier séparé par un développeur moins discipliné (ou tout simplement nouveau).

Donc, existe-t-il un moyen de forcer le compilateur à traiter tous les littéraux (virgule flottante) comme des flottants, comme avec le suffixe f? Même si c'est contre les spécifications, je m'en fiche. Ou d'autres solutions? Le compilateur est gcc, soit dit en passant.

70
Zeus

-fsingle-precision-constant peut être utilisé. Il provoque le chargement de constantes à virgule flottante en simple précision, même si ce n'est pas exact.

Remarque - Cela utilisera également des constantes de précision simple dans les opérations sur les variables de double précision.

77
ameyCU

Utilisez plutôt des avertissements: -Wdouble-promotion met en garde contre implicite float to double promotion, comme dans votre exemple. -Wfloat-conversion vous avertira des cas où vous pouvez encore affecter des doubles à des flottants.

C'est une meilleure solution que de forcer simplement des valeurs doubles à la valeur flottante la plus proche. Votre code à virgule flottante est toujours conforme et vous n'aurez aucune mauvaise surprise si une valeur double contient une valeur positive, disons inférieure à FLT_DENORM_MIN (en supposant IEEE-754) ou supérieur à FLT_MAX.

50
Brett Hale

Vous pouvez convertir les constantes définies en (float) partout où ils sont utilisés, l'optimiseur doit faire son travail. Il s'agit d'une solution portable.

#define LIMIT 2.5

if (x < (float)LIMIT) ...
1
Yves Daoust

Le -Wunsuffixed-float-constants L'indicateur pourrait également être utilisé, peut-être combiné avec certaines des autres options de la réponse acceptée ci-dessus. Cependant, cela n'attrapera probablement pas les constantes non suffixées dans les en-têtes du système. Aurait besoin d'utiliser -Wsystem-headers pour les attraper aussi. Pourrait générer beaucoup d'avertissements ...

1
delsauce