297 votes

Comment déterminer si une décimale/double est un nombre entier ?

Comment savoir si une valeur décimale ou double est un nombre entier ?

Par exemple :

decimal d = 5.0; // Would be true
decimal f = 5.5; // Would be false

ou

double d = 5.0; // Would be true
double f = 5.5; // Would be false

La raison pour laquelle j'aimerais savoir cela est que je peux déterminer par programme si je veux sortir la valeur en utilisant la fonction .ToString("N0") ou .ToString("N2") . S'il n'y a pas de valeur décimale, je ne veux pas le montrer.

0 votes

Math.Floor(float.Parse(inputValue)) == float.Parse(inputValue)

540voto

Mark Rushakoff Points 97350

Pour les nombres à virgule flottante, n % 1 == 0 est généralement le moyen de vérifier s'il y a quelque chose après la virgule.

public static void Main (string[] args)
{
    decimal d = 3.1M;
    Console.WriteLine((d % 1) == 0);
    d = 3.0M;
    Console.WriteLine((d % 1) == 0);
}

Sortie :

False
True

Mise à jour : Comme @Adrian Lopez l'a mentionné ci-dessous, la comparaison avec une petite valeur epsilon éliminera les erreurs de calcul en virgule flottante. Puisque la question porte sur double les valeurs ci-dessous seront plus preuve de calcul en virgule flottante réponse :

Math.Abs(d % 1) <= (Double.Epsilon * 100)

114 votes

Cela fonctionne lorsque le nombre est un nombre entier au départ, mais pas nécessairement lorsque le nombre est le résultat d'un calcul en virgule flottante. Que diriez-vous de quelque chose comme "(d % 1) < epsilon" où epsion est une petite valeur ?

11 votes

C'est dommage que la meilleure réponse dans ce fil soit un commentaire, plutôt que la réponse acceptée. Bien joué, Adrian.

0 votes

La réponse donnée par @MarkRushakoff échoue pour l'entrée comme 2.719601835756618E9 qui est un double

58voto

Erik Funkenbusch Points 53436

Il existe un grand nombre de façons de procéder. Par exemple :

double d = 5.0;
bool isInt = d == (int)d;

Vous pouvez également utiliser le modulo.

double d = 5.0;
bool isInt = d % 1 == 0;

0 votes

L'une d'entre elles serait-elle plus rapide que l'autre ? Je veux faire cela dans un contexte sensible aux performances.

0 votes

@Basil - Cela dépend des circonstances. Vous devriez faire quelques timings pour vous-même et juger.

5 votes

Math.Abs(d-(int)d) < double.Epsilon est plus sûr que d == (int)d

26voto

Dan Tao Points 60518

Que pensez-vous de ça ?

public static bool IsInteger(double number) {
    return number == Math.Truncate(number);
}

Même code pour decimal .

Mark Byers a soulevé un bon point, en fait : ce n'est peut-être pas ce que vous vraiment veulent. Si ce que vous vraiment Ce qui compte, c'est si un nombre arrondi aux deux décimales les plus proches est un entier vous pourriez faire ceci à la place :

public static bool IsNearlyInteger(double number) {
    return Math.Round(number, 2) == Math.Round(number);
}

1 votes

Peut-être mettre à jour votre solution et ajouter : && number<int.MaxValue && number>int.MinValue

13voto

Mark Byers Points 318575

Si les solutions proposées semblent fonctionner dans le cas d'exemples simples, c'est une mauvaise idée de procéder ainsi en général. Un nombre peut ne pas être exactement un nombre entier, mais lorsque vous essayez de le formater, il est suffisamment proche d'un nombre entier pour que vous obteniez 1.000000 . Cela peut se produire si vous effectuez un calcul qui, en théorie, devrait donner exactement 1, mais qui, en pratique, donne un nombre très proche de 1 mais pas exactement égal à 1 en raison d'erreurs d'arrondi.

Formatez-la d'abord et si votre chaîne se termine par un point suivi de zéros, enlevez-les. Vous pouvez également utiliser certains formats qui suppriment automatiquement les zéros de fin de chaîne. Cela peut être suffisant pour votre cas.

double d = 1.0002;
Console.WriteLine(d.ToString("0.##"));
d = 1.02;
Console.WriteLine(d.ToString("0.##"));

Sortie :

1
1.02

0 votes

@Mark Cela semble intéressant. Avez-vous un exemple d'un format qui supprime les zéros de fin de ligne ?

0 votes

Je conviens que c'est plus sûr et que c'est ce que le PO devrait probablement faire, mais ce n'est pas une réponse à la question plus étroite (mais plus intéressante) de savoir si une valeur a une partie fractionnaire ou non.

3 votes

@Clifford : J'essaie généralement de répondre en me basant sur ce qui est le mieux pour résoudre le problème du PO, et non sur ce que dit le titre. Les titres sont rarement une description précise du problème.

13voto

Puppy Points 90818
bool IsInteger(double num) {
    if (ceil(num) == num && floor(num) == num)
        return true;
    else
        return false;
}

Problemo solvo.

Edit : Pwned by Mark Rushakoff.

4 votes

Ou simplement return ceil(num) == num && floor(num) == num;

21 votes

Ou simplement return ceil(num) == floor(num);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X