为什么 C # 中的整数除法返回的是整数而不是浮点数?

有人知道为什么 C # 中的整数除法会返回一个整数而不是浮点数吗? 它背后的理念是什么? (它仅仅是 C/C + + 的遗产吗?)

C # :

float x = 13 / 4;
//== operator is overridden here to use epsilon compare
if (x == 3.0)
print 'Hello world';

该守则的结果将是:

'Hello world'

严格地说,没有整数除法这种东西(根据定义除法是一种产生有理数的操作,整数是其中一个非常小的子集。)

248408 次浏览

参见 C # 规格。除法运算符有三种类型

  • 整数除法
  • 浮点部门
  • 十进制除法

在你的例子中,我们有整数除法,适用以下规则:

除法将结果四舍五入为零,绝对值为 结果是小于 两个操作数的商的绝对值。结果为零 当两个操作数具有相同的符号和零或 当两个操作数有相反的符号时为负。

我认为 C # 之所以对整数使用这种类型的除法(有些语言返回浮动结果)是因为硬件整数除法更快更简单。

由于不使用任何后缀,字面值 134被解释为整数:

手册 :

如果文字没有后缀,那么它有这些类型中的第一种类型,其值可以在这些类型中表示: intuintlongulong

因此,由于你声明 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 x = 13 / 4;

请注意,您仍然要除整数,这将隐式地强制转换为 float: 结果将是 3.0。使用 f后缀(13f4f)将操作数显式声明为 float。

每种数据类型都能够重载每个运算符。如果分子和分母都是整数,则整数类型将执行除法操作并返回整数类型。如果要进行浮点除法,必须先将一个或多个数字强制转换为浮点类型,然后再进行除法。例如:

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

或者,如果你使用的是字面意思:

float x = 13f / 4f;

记住,浮点数并不精确。如果您关心精度,可以使用类似于十进制类型的代码。

虽然这是常见的新程序员执行整数除法的错误时,他们实际上是要使用浮点除法,在实际操作中整数除法是一个非常常见的操作。如果您假设人们很少使用它,并且每次进行除法时总是需要记住转换为浮点数,那么您就错了。

首先,整数除法相当快,所以如果你只需要一个整数结果,人们会希望使用更有效的算法。

其次,有许多算法使用整数除法,如果除法的结果总是一个浮点数,那么每次都必须对结果进行四舍五入。我想到的一个例子就是改变一个数字的基数。计算每个数字包括一个数字的整数除法和余数除法,而不是数字的浮点除法。

由于这些(以及其他相关)原因,整数除法会产生一个整数。如果你想得到两个整数的浮点除法,你只需要记住将其中一个转换为 double/float/decimal

只是个 基本操作

还记得你学习除法的时候吗? 一开始我们解出了 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 具有更高的精度和更小的范围)。

作为一个小技巧,你可以使用 Var,这样编译器就会告诉你所期望的类型:

int a = 1;
int b = 2;
var result = a/b;

你的编译器会告诉你这里的 结果类型是 Int