Gardez à l'esprit que la plupart des techniques présentées ici sont valables en supposant que l'erreur d'arrondi due aux calculs antérieurs n'est pas un facteur. Par exemple, vous pourrait utiliser roundf
comme ceci :
float z = 1.0f;
if (roundf(z) == z) {
printf("integer\n");
} else {
printf("fraction\n");
}
Le problème avec cette technique et d'autres techniques similaires (telles que ceilf
, le casting à long
) est que, bien qu'ils fonctionnent parfaitement pour les constantes de nombres entiers, ils échouent si le nombre est le résultat d'un calcul qui a été sujet à une erreur d'arrondi en virgule flottante. Par exemple :
float z = powf(powf(3.0f, 0.05f), 20.0f);
if (roundf(z) == z) {
printf("integer\n");
} else {
printf("fraction\n");
}
Imprime "fraction", même si (3 1/20 ) 20 devrait être égal à 3, car le résultat réel du calcul a fini par être 2.9999992847442626953125 .
Toute méthode similaire, qu'elle soit fmodf
ou autre, est soumis à cela. Dans les applications qui effectuent des calculs complexes ou sujets aux arrondis, on souhaite généralement définir une certaine valeur de "tolérance" pour ce qui constitue un "nombre entier" (cela vaut pour les comparaisons d'égalité en virgule flottante en général). Nous appelons souvent cette tolérance epsilon . Par exemple, disons que nous pardonnons à l'ordinateur jusqu'à +/- 0,00001 d'erreur d'arrondi. Alors, si nous testons z
nous pouvons choisir un epsilon de 0.00001 et faire :
if (fabsf(roundf(z) - z) <= 0.00001f) {
printf("integer\n");
} else {
printf("fraction\n");
}
Vous ne voulez pas vraiment utiliser ceilf
ici, car par exemple ceilf(1.0000001)
est 2 et non 1, et ceilf(-1.99999999)
est -1 et non -2.
Vous pourriez utiliser rintf
à la place de roundf
si vous préférez.
Choisissez une valeur de tolérance adaptée à votre application (et oui, parfois la tolérance zéro est appropriée). Pour plus d'informations, consultez cet article sur comparaison de nombres à virgule flottante .
9 votes
Votre méthode échoue lorsque le nombre est supérieur à la valeur entière maximale autorisée.
0 votes
Voir ma réponse pour une solution au problème de l'approche de l'OP.
0 votes
La réponse correcte est certainement : vous posez la mauvaise question.
0 votes
John Marshall : Alors, quelle serait la bonne question ?
1 votes
Eh bien, qu'est-ce que vous essayez de faire ? Si vous stockez une valeur dans un
float
On peut supposer que c'est parce que vous voulez faire de l'arithmétique en virgule flottante sur cette variable. La question qui se pose alors est la suivante : cette variable, dont la valeur est un peu floue de manière spécifique au domaine et de manière qui dépend de la prudence avec laquelle vous effectuez l'arithmétique, a-t-elle une valeur qui est une intégrale floue ? Pour répondre à cette question de manière significative, vous devez tenir compte de la fluidité spécifique au domaine. Ou, en d'autres termes : quel est ce scénario dans lequel l'approche correcte n'est pas de stocker votre valeur dans un fichier de typeint
de la taille appropriée ?0 votes
Vous dites "analysé", je vais donc supposer que ce fichier est un fichier texte, contenant des représentations textuelles de données numériques. La réponse à votre problème d'analyse syntaxique consisterait à analyser chaque élément dans un fichier de type
int
oufloat
en fonction de ce qu'est réellement le texte, et le renvoie probablement dans une union (avec un drapeau indiquant de quoi il s'agit, bien sûr). Ainsi, votre question de savoir si un élément est uneint
est trivial, et votre code convertit explicitement les ints enfloat
lorsque cela est nécessaire. Ou, plus simplement : vous avez la représentation textuelle de votre nombre. C'est un int si ça ne correspond pas à/[.Ee]/
essentiellement.0 votes
(Vous avez besoin d'un modèle plus intelligent si vous avez des constantes entières hexagonales, évidemment.) Et cela répond à une question légèrement différente. Si un élément est écrit sous la forme 1.5E+2, voulez-vous effectuer des opérations entières sur 150, ou voulez-vous avertir que cela ne ressemble pas à un entier ? Que l'avertissement dans ce cas soit un bug ou une fonctionnalité est dans l'œil de celui qui regarde...
0 votes
@JohnMarshall, peut-être qu'il analyse JSON et veut stocker le nombre dans une union (comme le font de nombreuses bibliothèques JSON). Il pourrait vouloir tirer parti d'une fonction standard ou de bibliothèque pour effectuer l'analyse syntaxique réelle, ce qui n'est pas trivial à faire correctement. C'est ce que j'essaie de faire moi-même et c'est ce qui m'a conduit à cette question.