95 votes

Meilleur moyen d'obtenir la partie entière d'un nombre décimal

Quelle est la meilleure façon de renvoyer la partie entière d'un nombre décimal (en c#) ? (Cela doit fonctionner pour de très grands nombres qui peuvent ne pas tenir dans un int).

GetIntPart(343564564.4342) >> 343564564
GetIntPart(-323489.32) >> -323489
GetIntPart(324) >> 324

Le but de ceci est : J'insère un champ décimal (30,4) dans la base de données et je veux m'assurer que je n'essaie pas d'insérer un nombre trop long pour le champ. La détermination de la longueur de la partie entière du nombre décimal fait partie de cette opération.

0 votes

Vous ne pouvez pas obtenir la partie int ; vous pouvez obtenir la partie nombre entier et laisser tomber la partie fractionnaire. La partie entière d'un Decimal peut facilement déborder d'un int et soit jeter ou envelopper, tuant silencieusement votre code.

1 votes

C'est pourquoi cette question n'est pas aussi simple qu'elle le semble. J'ai besoin que cela fonctionne pour les très grands nombres de manière aussi fiable que pour les petits nombres. Cependant, "nombre entier" est plus précis que "int" - je vais reformuler la question ci-dessus.

222voto

Will Points 76760

Au fait, (int)Decimal.MaxValue va déborder. Vous ne pouvez pas obtenir la partie "int" d'un décimal parce que le décimal est trop gros pour être placé dans la case int. Je viens de vérifier... il est même trop grand pour un long (Int64).

Si vous voulez que le bit d'une valeur décimale soit à la GAUCHE du point, vous devez faire ceci :

Math.Truncate(number)

et retourner la valeur comme... Un DECIMAL ou un DOUBLE.

edit : Truncate est définitivement la bonne fonction !

0 votes

Le résultat est donc un décimal ou un double qui n'aura jamais rien après le point mais il n'y a pas d'objet intégré pour stocker le résultat comme un "int" (sans décimales), ce qui semble un peu boiteux ?

0 votes

@CodeBlend : Il n'y a pas beaucoup d'intérêt à concevoir des frameworks autour d'une volonté de perdre en précision.

0 votes

@CodeBlend : Vous perdriez toujours de la précision parce que vous coupez les valeurs décimales d'un nombre. Je ne sais pas où vous voulez en venir.

25voto

Pwninstein Points 7293

Je pense System.Math.Truncate est ce que vous recherchez.

4voto

Keith Points 46288

Ça dépend de ce que vous faites.

Par exemple :

//bankers' rounding - midpoint goes to nearest even
GetIntPart(2.5) >> 2
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -6

o

//arithmetic rounding - midpoint goes away from zero
GetIntPart(2.5) >> 3
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -7

La valeur par défaut est toujours la première, ce qui peut être surprenant mais c'est très sensé .

Votre casting explicite fera l'affaire :

int intPart = (int)343564564.5
// intPart will be 343564564

int intPart = (int)343564565.5
// intPart will be 343564566

D'après la façon dont vous avez formulé la question, on dirait que ce n'est pas ce que vous voulez - vous voulez que le plancher soit toujours atteint.

Je le ferais :

Math.Floor(Math.Abs(number));

Vérifiez également la taille de votre decimal - ils peuvent être assez grands, donc vous devrez peut-être utiliser une long .

0 votes

(long)Decimal.MaxValue déborde.

0 votes

C'est vrai - je suppose que c'est pour cela que Math.Truncate(decimal) renvoie des décimales.

0 votes

En C#, le casting en int n'arrondit pas, donc (int)0.6f sera 0, et (int)343564565.5 se terminera par 5, pas 6. Essayez ici : repl.it/repls/LuxuriousCheerfulDistributeddatabase

1voto

Noldorin Points 67794

Il suffit de le lancer, comme tel :

int intPart = (int)343564564.4342

Si vous souhaitez toujours l'utiliser comme une décimale dans des calculs ultérieurs, alors Math.Truncate (ou éventuellement Math.Floor si vous souhaitez un certain comportement pour les nombres négatifs) est la fonction qu'il vous faut.

5 votes

C'est mal, mal, mal. Si le résultat est supérieur à ce qu'un Int32 peut contenir, soit il lèvera une exception, soit (encore pire ! !!) il débordera silencieusement et se retournera, vous donnant un résultat complètement incorrect sans même que vous le sachiez.

2 votes

Non, ça ne l'est pas. mauvais . Elle peut ne pas être valable pour les valeurs décimales/à virgule flottante très importantes, mais elle est parfaitement adaptée à la plupart des situations. Les nombres sont très souvent contraints d'être suffisamment bas lors du codage, donc cela ne doit pas être un problème. J'ai également fourni une solution Math.Truncate qui fonctionne pour toutes les valeurs.

2 votes

Je vois pourquoi tu es en colère contre moi. Le fait est que ta réponse est fausse. Tu lui dis de prendre le risque que ça ne casse pas parce que, hé, beaucoup de chiffres sont petits. C'est un risque insensé à prendre. Vous devriez modifier votre réponse et supprimer tout sauf Math.Truncate car c'est la seule partie correcte.

0voto

Amit Gohel Points 1

Une façon très simple de séparer la valeur et sa partie fractionnée.

double  d = 3.5;
int i = (int)d;
string s = d.ToString();
s = s.Replace(i + ".", "");

s est une partie fractionnaire = 5 et
i est une valeur entière = 3

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