Почему целочисленное деление в C# возвращает целое число, а не float?


кто-нибудь знает, почему целочисленное деление в C# возвращает целое число, а не float? Что за идея стоит за этим? (Это только наследие C / C++?)

В C#:

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

результатом этого кода будет:

'Hello world'
7 100

7 ответов:

В то время как новый программист часто совершает эту ошибку, выполняя целочисленное деление, когда они фактически намеревались использовать деление с плавающей запятой, на практике целочисленное деление является очень распространенной операцией. Если вы предполагаете, что люди редко используют его, и что каждый раз, когда вы делаете разделение, вам всегда нужно помнить о приведении к плавающим точкам, вы ошибаетесь.

во-первых, целочисленное деление довольно быстро, поэтому, если вам нужен только результат целого числа, один хотелось бы использовать более эффективный алгоритм.

во-вторых, существует ряд алгоритмов, которые используют целочисленное деление, и если бы результат деления всегда был числом с плавающей запятой, вы были бы вынуждены каждый раз округлять результат. Один пример с верхней части моей головы-это изменение основания числа. Вычисление каждой цифры включает в себя целочисленное деление числа вместе с остатком, а не деление числа с плавающей запятой.

потому что из этих (и других связанных) причин целочисленное деление приводит к целому числу. Если вы хотите получить деление с плавающей запятой двух целых чисел, вам просто нужно не забыть бросить один в A double/float/decimal.

См. C# спецификация. Существует три типа операторов деления

  • целочисленное деление
  • деление с плавающей запятой
  • десятичное деление

в вашем случае мы имеем целочисленное деление, при этом применяются следующие правила:

деление округляет результат до нуля, а абсолютное значение результатом является максимально возможное целое число, которое меньше абсолютное значение частное двух операндов. Результат равен нулю или положительный, когда два операнда имеют одинаковый знак и ноль или отрицательно, когда два операнда имеют противоположные знаки.

Я думаю, что причина, по которой C# использует этот тип деления для целых чисел (некоторые языки возвращают плавающий результат), - это аппаратное деление целых чисел быстрее и проще.

каждый тип данных способен перегружать каждый оператор. Если числитель и знаменатель являются целыми числами, то целочисленный тип выполнит операцию деления и вернет целочисленный тип. Если требуется разделение с плавающей запятой, перед разделением необходимо привести одно или несколько чисел к типам с плавающей запятой. Например:

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

или, если вы используете литералы:

float x = 13f / 4f;

имейте в виду, плавающие точки не являются точными. Если тебе не все равно о точности, вместо этого используйте что-то вроде десятичного типа.

так как вы не используете суффикс, литералы 13 и 4 интерпретируется как целое число:

инструкцию:

если литерал не имеет суффикса, то есть первый из этих типов, в которых его значение может быть представлено: int,uint,long,ulong.

таким образом, поскольку вы объявляете 13 как целое число, целочисленное деление будет выполнено:

инструкцию:

для операции вида x / y применяется разрешение перегрузки двоичного оператора для выбора конкретной реализации оператора. Операнды преобразуются в типы параметров выбранного оператора, а тип результата является типом возвращаемого оператором.

ниже перечислены предопределенные операторы деления. Все операторы вычисляют частное от x и y.

целое число подразделение:

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

и так происходит округление вниз:

деление округляет результат до нуля, и абсолютное значение результата является максимально возможным целым числом, которое меньше абсолютного значения частного двух операндов. Результат равен нулю или положительному, когда два операнда имеют один и тот же знак, и нулю или отрицательному, когда два операнда имеют противоположные знаки.

если вы делаете следующее:

int x = 13f / 4f;

вы получите ошибку компилятора, так как деление с плавающей запятой (/ оператор 13f) приводит к float, который не может быть приведен к int неявно.

если вы хотите, чтобы деление было делением с плавающей запятой, вам нужно будет сделать результат плавающим:

float x = 13 / 4;

обратите внимание, что вы все равно будете делить целые числа, которые будут неявно брошены в float: результат будет 3.0. Чтобы явно объявить операнды как поплавок, используя f суффикс (13f,4f).

просто основные операции.

помните, когда вы научились делить. В начале мы решили 9/6 = 1 with remainder 3.

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

оператор / - в сочетании с оператором %-используются для извлечения этих значений.

может быть полезно:

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

результат всегда будет иметь тип, который имеет больший диапазон числителя и знаменателя. Исключения-byte и short, которые производят 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

неявное преобразование между типами с плавающей запятой и десятичным типом отсутствует, поэтому разделение между ними не допускается. Вы должны явно привести и решить, какой из них вы хотите (Decimal имеет большую точность и меньший диапазон по сравнению с типами с плавающей запятой).