web-dev-qa-db-fra.com

Pourquoi le "f" est-il requis lors de la déclaration de flotteurs?

Exemple:

float timeRemaining = 0.58f;

Pourquoi le f est-il requis à la fin du nombre?

75
Thomas

Votre déclaration de float contient deux parties:

  1. Il déclare que la variable timeRemaining est de type float.
  2. Il attribue la valeur 0.58 à cette variable.

Le problème se produit dans la partie 2.

Le côté droit est évalué seul. Selon la spécification C #, un nombre contenant un point décimal sans suffixe est interprété comme un double.

Nous avons donc maintenant une valeur double à attribuer à une variable de type float. Pour ce faire, il doit exister une conversion implicite de double en float. Il n’existe pas de conversion de ce type car vous risquez (et dans ce cas de perdre) des informations lors de la conversion.

La raison en est que la valeur utilisée par le compilateur n'est pas vraiment 0,58, mais la valeur à virgule flottante la plus proche de 0,58, qui est 0,57999999999999999799565962351581366 ... pour double et exactement 0,579999946057796478271484375 pour float.

À proprement parler, le f n'est pas requis. Vous pouvez éviter de devoir utiliser le suffixe f en convertissant la valeur en float:

float timeRemaining = (float)0.58;
84
Jeffrey Sax

Comme le compilateur peut utiliser plusieurs types numériques pour représenter la valeur 0.58: float , double et decimal . Sauf si vous êtes d'accord avec le compilateur qui en choisit un pour vous, vous devez vous en passer de l'ambiguïté.

La documentation de double indique que si vous ne spécifiez pas le type vous-même, le compilateur choisit toujours double comme type de tout littéral numérique réel:

Par défaut, un littéral numérique réel situé à droite de l'opérateur d'affectation est traité comme un double. Toutefois, si vous souhaitez qu'un nombre entier soit traité comme un double, utilisez le suffixe d ou D.

Ajouter le suffixe f crée un float; le suffixe d crée un double; le suffixe m crée un decimal. Tous ces éléments fonctionnent également en majuscules.

Cependant, cela ne suffit pas encore pour expliquer pourquoi cela ne compile pas:

float timeRemaining = 0.58;

La moitié manquante de la réponse est que la conversion de la double0.58 au floattimeRemaining perd potentiellement des informations, aussi le compilateur refuse-t-il de les appliquer implicitement. Si vous ajoutez une conversion explicite, la conversion est effectuée. Si vous ajoutez le suffixe f, aucune conversion ne sera nécessaire. Dans les deux cas, le code serait alors compilé.

36
Jon

Le problème est que .NET, afin de permettre à certains types d’opérations implicites impliquant float et double, soit de spécifier explicitement ce qui doit se passer dans tous les scénarios impliquant des opérandes mixtes ou sinon, autoriser les conversions implicites entre les types dans un seul sens; Microsoft a choisi de suivre l'exemple de Java en autorisant la direction qui favorise parfois la précision, mais qui souvent sacrifie l'exactitude et crée généralement des problèmes.

Dans presque tous les cas, prendre la valeur double la plus proche d'une quantité numérique donnée et l'attribuer à un float donnera la valeur float la plus proche de cette même quantité. . Il existe quelques cas, tels que la valeur 9 007 199 791 611 905; la meilleure représentation float serait de 9 007 200 328 482 816 (ce qui correspond à une réduction de 536 870 911), mais le résultat de la meilleure représentation double (c'est-à-dire 9 007,199,791,611,904) à float ) En général, toutefois, convertir la meilleure représentation double d'une certaine quantité en float donnera la meilleure représentation possible float ou l'une des deux représentations qui sont essentiellement égales.

Notez que ce comportement souhaitable s’applique même aux extrêmes; Par exemple, la meilleure représentation float de la quantité 10 ^ 308 correspond à la représentation float obtenue en convertissant la meilleure représentation double de cette quantité. De même, la meilleure représentation float de 10 ^ 309 correspond à la représentation float obtenue en convertissant la meilleure représentation double de cette quantité.

Malheureusement, les conversions ne nécessitant pas de conversion explicite sont rarement aussi précises. La conversion de la meilleure représentation float d’une valeur en double ne donnera rarement rien de particulièrement proche de la meilleure représentation double de cette valeur et, dans certains cas, le résultat peut être erroné. Des centaines d'ordres de grandeur (par exemple, convertir la meilleure représentation float de 10 ^ 40 en double générera une valeur supérieure à la meilleure représentation double de 10 ^ 300.

Hélas, les règles de conversion sont ce qu'elles sont, il faut donc utiliser des typographies et des suffixes idiots lors de la conversion de valeurs dans le sens "sûr", et faire attention aux typecasts implicites dans le sens dangereux qui donneront fréquemment des résultats erronés.

2
supercat