157

有谁知道为什么 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'

严格来说,没有整数除法之类的东西(根据定义,除法是一种产生有理数的运算,整数是其中的一个很小的子集。)

4

8 回答 8

117

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

首先,整数除法要快很多,所以如果你只需要一个整数结果,你会想要使用更有效的算法。

其次,有许多使用整数除法的算法,如果除法的结果总是一个浮点数,你将不得不每次都对结果进行四舍五入。我脑海中浮现的一个例子是改变一个数字的基数。计算每个数字涉及一个数字的整数除法以及余数,而不是数字的浮点除法。

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

于 2012-06-01T13:42:56.320 回答
82

请参阅 C#规范。除法运算符分为三种类型

  • 整数除法
  • 浮点除法
  • 小数除法

在您的情况下,我们有整数除法,并应用以下规则:

除法将结果向零舍入,结果的绝对值是小于两个操作数的商的绝对值的最大可能整数。当两个操作数具有相同符号时,结果为零或正,当两个操作数具有相反符号时,结果为零或负。

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

于 2012-06-01T13:34:42.617 回答
46

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

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

或者,如果您使用的是文字:

float x = 13f / 4f;

请记住,浮点数并不精确。如果您关心精度,请改用小数类型。

于 2012-06-01T13:42:40.060 回答
12

由于您不使用任何后缀,因此文字134被解释为整数:

手册

如果字面量没有后缀,则它具有可以表示其值的第一个类型: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 x = 13 / 4;

请注意,您仍将除以整数,这将隐式转换为浮点数:结果将是3.0. f使用后缀 ( 13f, )将操作数显式声明为浮点数4f

于 2012-06-01T13:35:48.117 回答
11

可能有用:

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
于 2016-11-07T22:17:16.113 回答
9

这只是一个基本操作

记住当你学会划分时。一开始我们解决了9/6 = 1 with remainder 3.

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

/-operator 与 %-operator 组合用于检索这些值。

于 2014-02-28T20:10:05.313 回答
8

结果将始终是分子和分母范围更大的类型。例外是 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 具有更高的精度和更小的范围)。

于 2017-05-01T19:16:03.713 回答
1

作为了解您所获得内容的一个小技巧,您可以使用var,因此编译器会告诉您期望的类型:

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

您的编译器会告诉您结果将是int类型。

于 2020-11-18T17:58:06.777 回答