Pourquoi Math.Floor (Double) renvoie-t-il une valeur de type Double?


103

J'ai besoin d'obtenir la valeur entière du côté gauche à partir d'une décimale ou d'un double. Pour Ex: je dois obtenir la valeur 4 de 4.6. J'ai essayé d'utiliser la fonction Math.Floor mais elle renvoie une valeur double, par exemple: elle renvoie 4.0 à partir de 4.6. La documentation MSDN indique qu'elle renvoie une valeur entière. Est-ce que j'ai râté quelque chose? Ou y a-t-il une manière différente de réaliser ce que je recherche?


2
La documentation MSDN indique qu'elle renvoie une valeur entière . La documentation MSDN indique que Math.Floor renvoie System.Double, pas un entier.
haut débit le

Une valeur entière est effectivement nécessaire, mais cela ne signifie pas qu'elle peut être stockée dans un "int" ou "long". Un "double" stocke avec succès toutes les valeurs entières dans une plage beaucoup plus large que juste "int" Notez que certaines valeurs entières peuvent être arrondies lorsque la partie mantisse n'a pas assez de bits pour stocker tous les chiffres de la valeur entière, lorsque son exposant de base 2 va au-dessus de 52: cet arrondi des valeurs entières en "double" peut se produire pour les entiers supérieurs à 2 ^ 52 ou inférieurs à -2 ^ 52 mais le résultat sera toujours l'entier le plus proche représentable; si vous utilisez "(long) Floor (x)", la conversion peut être largement erronée.
verdy_p

Notez cependant que la plage valide de valeurs entières qui peuvent être représentées dans un "double" est extrêmement grande, avec des valeurs absolues allant jusqu'à: (1 + (1 - 2 ^ −52)) × 2 ^ 1023 ≈ 1.7976931348623157E308; c'est bien plus que 2 ^ 63-1 avec "long". Cependant, la plage d'entiers qui peuvent tous être stockés séparément est plus restreinte, car un "double" n'a que 52 bits pour la mantisse (plus 1 bit implicite pour le bit le plus significatif, non stocké), ce qui signifie que "double" ne peut stocker que entiers exactement o seulement lorsque leur valeur absolue est inférieure à 2 ^ 53.
verdy_p

Malheureusement, Math.Floor () ne retourne pas de variable de type "Number" en interne en utilisant "Long" si possible, ou "Double" sinon uniquement pour les grands entiers arrondis. Et la bibliothèque Math standard ne gère pas ce type de numéro de variable unifié. Il existe d'autres bibliothèques mathématiques implémentant un type de nombre unifié, y compris des entiers longs, doubles ou grands codés en décimal compressé ou binaire sans perte de plage ou de précision prise en charge.
verdy_p

Réponses:


146

La plage de doubleest beaucoup plus large que celle de intou long. Considérez ce code:

double d = 100000000000000000000d;
long x = Math.Floor(d); // Invalid in reality

L'entier est en dehors de la plage de long- alors que vous attendez-vous à ce qu'il se passe?

En règle générale, vous savez que la valeur sera en fait dans la plage de intou long, vous la castez donc:

double d = 1000.1234d;
int x = (int) Math.Floor(d);

mais la responsabilité de cette distribution incombe au développeur, pas à Math.Floorlui-même. Il aurait été inutilement restrictif de le faire échouer avec une exception pour toutes les valeurs en dehors de la plage de long.


2
Floor renvoie une représentation entière de double, et il retourne double pour les calculs scientifiques, cette réponse n'est pas correcte car double a 64 bits et long a également 64 bits, mais double ne peut pas stocker les chiffres exacts des bits de poids faible même s'il peut être stocké correctement dans longtemps.
Akash Kava

1
@ Jon: comment vous venez n'avez pas pesé sur le débat qui fait rage sur la façon de faire un négatif nombre positif en C # ?: stackoverflow.com/questions/1348080/...
MusiGenesis

3
@Jon: prenez votre temps. Il s'avère que la communauté a découvert que multiplier un nombre positif par -1 le rendra négatif. Tout va bien sur StackOverflow.
MusiGenesis

1
@javapowered: Non, (int) 15.0 n'est pas 0. Quelque chose d'autre s'est mal passé, mais nous ne pouvons pas dire quoi à partir de cela. Veuillez créer un programme court mais complet démontrant cela, puis posez une question. Je pense que vous aurez du mal à reproduire ...
Jon Skeet

1
@MusiGenesis: <code> (int) IGNORE_RATIO * Volume </code> est calculé comme <code> (int) 0.15 * Volume </code>, mais le typecast s'applique uniquement au ratio, pas au résultat du produit, et vous obtenez <code> 0 * Volume </code> soit zéro! Utilisez plutôt <code> (int) (IGNORE_RATIO * Volume) </code> pour résoudre VOTRE bogue.
verdy_p

11

Selon MSDN, Math.Floor (double) renvoie un double: http://msdn.microsoft.com/en-us/library/e0b5f0xb.aspx

Si vous le voulez comme un int:

int result = (int)Math.Floor(yourVariable);

Je peux voir comment l'article MSDN peut être trompeur, ils auraient dû spécifier que si le résultat est un "entier" (dans ce cas signifiant un nombre entier), il est toujours de TYPE Double


Merci pour votre réponse. En fait, je regardais cet article: msdn.microsoft.com/en-us/library/e0b5f0xb.aspx Mais de toute façon, je vais essayer votre suggestion. Je vous remercie.

Eh bien vrai, il dit en haut "renvoie un entier" mais le type est spécifié en dessous: public static double Floor (double d)
Neil N

3
integer! = int( answers.com/integer ) - les entiers peuvent être stockés dans Double(voir la réponse de Jon), et il y a un nombre infini d'entiers qui ne peuvent pas être stockés dans un fichier int.
Shog9

Shog, je n'ai pas dit qu'ils ne pouvaient pas. Ce que j'ai dit, c'est "c'est toujours du TYPE Double"
Neil N

1
@Neil: droite - je voulais juste souligner la différence entre "entier" (nom d'un ensemble) et int(nom d'un type).
Shog9

4

Si vous avez juste besoin de la partie entière d'un nombre, transtypez le nombre en un int. Cela tronquera le nombre au point décimal.

double myDouble = 4.6;
int myInteger = (int)myDouble;

2
Il est important de noter que la intconversion se comporte différemment de Floor, pour les nombres négatifs. Floorsera toujours tronqué au nombre le plus négatif, tandis que le casting vers inttronquera vers 0.
Magnus


0

Le sol le laisse comme un double afin que vous puissiez faire plus de doubles calculs avec lui. Si vous le souhaitez en tant qu'int, convertissez le résultat de floor en int. Ne transtypez pas le double d'origine comme un entier car les règles pour le plancher sont différentes (IIRC) pour les nombres négatifs.


0
Convert.ToInt32(Math.Floor(Convert.ToDouble(value)))

Cela vous donnera la valeur exacte que vous voulez si vous prenez les 4.6retours 4en sortie.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.