Почему целочисленное деление в С# возвращает целое число, а не float?
Кто-нибудь знает, почему целочисленное деление в С# возвращает целое число, а не float? Какова идея этого? (Это только наследие 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'
Строго говоря, нет такого понятия, как целочисленное деление (деление по определению - операция, которая производит рациональное число, целые числа - очень небольшое подмножество).
Ответы
Ответ 1
В то время как обычный программист обычно совершает эту ошибку при выполнении целочисленного деления, когда они на самом деле предназначены для использования деления с плавающей запятой, на практике целочисленное деление является очень распространенной операцией. Если вы предполагаете, что люди редко используют его, и что каждый раз, когда вы выполняете разделение, вам всегда нужно помнить, что нужно бросать в плавающие точки, вы ошибаетесь.
Во-первых, целочисленное деление выполняется довольно быстро, поэтому, если вам нужен только результат целого числа, хотелось бы использовать более эффективный алгоритм.
Во-вторых, существует ряд алгоритмов, которые используют целочисленное деление, и если результат деления всегда был числом с плавающей запятой, вы каждый раз должны были бы округлять результат. Один пример от верхней части моей головы - изменение базы числа. Вычисление каждой цифры включает в себя целочисленное деление числа вместе с остатком, а не деление числа с плавающей запятой.
Из-за этих (и других связанных) причин целочисленное деление приводит к целому числу. Если вы хотите получить деление с плавающей запятой двух целых чисел, вам просто нужно запомнить одну из них: double
/float
/decimal
.
Ответ 2
См. с# спецификацию. Существует три типа операторов деления
- Целочисленное деление
- Деление с плавающей точкой
- Десятичное деление
В вашем случае у нас есть целочисленное деление с применением следующих правил:
Деление округляет результат до нуля, а абсолютное значение результат - максимально возможное целое число, которое меньше, чем абсолютное значение отношения двух операндов. Результат ноль или положительный, когда два операнда имеют одинаковый знак и ноль или отрицательный, когда два операнда имеют противоположные знаки.
Я думаю, что причина, по которой С# использует этот тип деления для целых чисел (некоторые языки возвращают плавающий результат), заключается в аппаратном - деление целых чисел происходит быстрее и проще.
Ответ 3
Каждый тип данных способен перегружать каждого оператора. Если и числитель, и знаменатель являются целыми числами, целочисленный тип выполнит операцию деления и вернет целочисленный тип. Если вы хотите деление с плавающей запятой, перед тем, как делить их, вы должны отбросить одно или несколько из числа до типов с плавающей запятой. Например:
int x = 13;
int y = 4;
float x = (float)y / (float)z;
или, если вы используете литералы:
float x = 13f / 4f;
Имейте в виду, что плавающие точки не точны. Если вы заботитесь о точности, вместо этого используйте что-то вроде десятичного.
Ответ 4
Поскольку вы не используете какой-либо суффикс, литералы 13
и 4
интерпретируются как integer:
Руководство:
Если литерал не имеет суффикса, он имеет первый из этих типов, в котором может быть представлено его значение: 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
) приводит к поплавке, которая не может быть введена в int неявно.
Если вы хотите, чтобы деление было делением с плавающей запятой, вам нужно сделать результат float:
float x = 13 / 4;
Обратите внимание, что вы все равно разделите целые числа, которые неявно будут отлиты для float: результат будет 3.0
. Чтобы явно объявить операнды как float, используя суффикс f
(13f
, 4f
).
Ответ 5
Его просто основная операция.
Помните, когда вы научились делиться. Вначале мы решили 9/6 = 1 with remainder 3
.
9 / 6 == 1 //true
9 % 6 == 3 // true
Для получения этих значений используется/-оператор в комбинации с% -оператором.
Ответ 6
Может быть полезно:
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
Ответ 7
Результат всегда будет иметь тип, который имеет больший диапазон числителя и знаменателя. Исключения составляют байты и короткие, которые производят 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 имеет более высокую точность и меньший диапазон по сравнению с типами с плавающей запятой).
Ответ 8
Если вы хотите получить результат с плавающей точкой, вам нужно будет объявить результат как тип float и набросить числитель или знаменатель.