web-dev-qa-db-fra.com

Pourquoi la division entière en C # renvoie-t-elle un entier et non un float?

Est-ce que quelqu'un sait pourquoi la division entière en C # renvoie un entier et non un float? Quelle est l'idée derrière cela? (Est-ce seulement un héritage de C/C++?)

En C #:

float x = 13 / 4;   
//imagine I used have an overridden == operator here to use epsilon compare
if (x == 3.0)
   print 'Hello world';

Le résultat de ce code serait:

'Hello world'

Strictement parlant, la division entière n'existe pas (la division par définition est une opération qui produit un nombre rationnel, les entiers étant un très petit sous-ensemble de ce qui est.)

117
BanditoBunny

Bien qu'il soit courant pour un nouveau programmeur de commettre cette erreur de division en nombres entiers alors qu'il était censé utiliser la division en virgule flottante, dans la pratique, la division en nombres entiers est une opération très courante. Si vous supposez que les gens l'utilisent rarement, et que chaque fois que vous faites une division, vous devez toujours vous rappeler de lancer les jets en points flottants, vous vous trompez.

Tout d’abord, la division des nombres entiers est un peu plus rapide, donc si vous n’avez besoin que d’un nombre entier, vous voudrez utiliser l’algorithme plus efficace.

Deuxièmement, il existe un certain nombre d'algorithmes qui utilisent la division entière, et si le résultat de la division était toujours un nombre à virgule flottante, vous seriez obligé d'arrondir le résultat à chaque fois. Un exemple qui me vient à l’esprit est de changer la base d’un nombre. Le calcul de chaque chiffre implique la division entière d'un nombre avec le reste, plutôt que la division en virgule flottante du nombre.

En raison de ces raisons (et d'autres raisons connexes), la division entière donne un entier. Si vous voulez obtenir la division en virgule flottante de deux entiers, il vous suffit de vous rappeler d'en convertir un en un double/float/decimal.

79
Servy

Voir C # spécification . Il y a trois types d'opérateurs de division

  • Division entière
  • Division en virgule flottante
  • Division décimale

Dans votre cas, nous avons la division Integer, avec les règles suivantes appliquées:

La division arrondit le résultat vers zéro et la valeur absolue du résultat est le plus grand nombre entier possible inférieur à la valeur absolue du quotient des deux opérandes. Le résultat est zéro ou positif lorsque les deux opérandes ont le même signe et zéro ou négatif lorsque les deux opérandes ont des signes opposés.

Je pense que la raison pour laquelle C # utilise ce type de division pour les entiers (certaines langues renvoient des résultats flottants) est matérielle - la division des entiers est plus rapide et plus simple.

73

Chaque type de données est capable de surcharger chaque opérateur. Si le numérateur et le dénominateur sont des nombres entiers, le type entier effectuera l'opération de division et renverra un type entier. Si vous voulez une division en virgule flottante, vous devez convertir un ou plusieurs des nombres en types à virgule flottante avant de les diviser. Par exemple:

int x = 13;
int y = 4;
float x = (float)y / (float)z;

ou, si vous utilisez des littéraux:

float x = 13f / 4f;

Gardez à l'esprit, les points flottants ne sont pas précis. Si vous tenez à la précision, utilisez quelque chose comme le type décimal, à la place.

34
Steven Doggart

Puisque vous n'utilisez aucun suffixe, les littéraux 13 et 4 sont interprétés comme un entier:

Manuel :

Si le littéral n'a pas de suffixe, il possède le premier de ces types dans lequel sa valeur peut être représentée: int, uint, long, ulong.

Ainsi, puisque vous déclarez 13 en entier, la division en entier sera effectuée:

Manuel :

Pour une opération de la forme x/y, la résolution de surcharge d'opérateur binaire est appliquée pour sélectionner une implémentation d'opérateur spécifique. Les opérandes sont convertis en types de paramètres de l'opérateur sélectionné et le type du résultat correspond au type de retour de l'opérateur.

Les opérateurs de division prédéfinis sont énumérés ci-dessous. Les opérateurs calculent tous le quotient de x et y.

Division entière:

int operator /(int x, int y);
uint operator /(uint x, uint y);
long operator /(long x, long y);
ulong operator /(ulong x, ulong y);

Et ainsi arrondi se produit:

La division arrondit le résultat vers zéro et la valeur absolue du résultat est le plus grand nombre entier possible inférieur à la valeur absolue du quotient des deux opérandes. Le résultat est zéro ou positif lorsque les deux opérandes ont le même signe et zéro ou négatif lorsque les deux opérandes ont des signes opposés.

Si vous procédez comme suit:

int x = 13f / 4f;

Vous recevrez une erreur du compilateur, car une division en virgule flottante (l'opérateur / de 13f) génère un float, qui ne peut pas être transtypé de manière implicite.

Si vous voulez que la division soit une division à virgule flottante, vous devrez transformer le résultat en float:

float x = 13 / 4;

Notez que vous diviserez toujours les entiers, qui seront implicitement convertis en float: le résultat sera 3.0. Pour déclarer explicitement les opérandes en tant que float, utilisez le suffixe f (13f, 4f).

11
CodeCaster

C'est juste un opération de base.

Rappelez-vous quand vous avez appris à diviser. Au début, nous avons résolu 9/6 = 1 with remainder 3.

9 / 6 == 1  //true
9 % 6 == 3 // true

L'opérateur/en combinaison avec l'opérateur% sont utilisés pour récupérer ces valeurs.

6
L. Monty

Pourrait être utile:

double a = 5.0/2.0;   
Console.WriteLine (a);      // 2.5

double b = 5/2;   
Console.WriteLine (b);      // 2

int c = 5/2;   
Console.WriteLine (c);      // 2

double d = 5f/2f;   
Console.WriteLine (d);      // 2.5
4
primalshade

Le résultat sera toujours du type ayant la plus grande plage du numérateur et du dénominateur. Les exceptions sont byte et short, qui produisent int (Int32).

var a = (byte)5 / (byte)2;  // 2 (Int32)
var b = (short)5 / (byte)2; // 2 (Int32)
var c = 5 / 2;              // 2 (Int32)
var d = 5 / 2U;             // 2 (UInt32)
var e = 5L / 2U;            // 2 (Int64)
var f = 5L / 2UL;           // 2 (UInt64)
var g = 5F / 2UL;           // 2.5 (Single/float)
var h = 5F / 2D;            // 2.5 (Double)
var i = 5.0 / 2F;           // 2.5 (Double)
var j = 5M / 2;             // 2.5 (Decimal)
var k = 5M / 2F;            // Not allowed

Il n'y a pas de conversion implicite entre les types à virgule flottante et le type décimal. Par conséquent, la division entre eux n'est pas autorisée. Vous devez explicitement transtyper et décider lequel vous voulez (Decimal a plus de précision et une plage plus petite par rapport aux types à virgule flottante).

3
z m