请考虑以下事项:
void Foo(int start, int end)
{
int mid = (start + end) / 2;
}
void Bar(int start, int end)
{
int mid = (start + end) * 0.5;
}
为什么Foo
成功编译而Bar
没有?除以2
隐式地将结果转换为int
,而乘以0.5
会得到未投放的double
:
无法将type' double隐式转换为int。显式转换 存在(你是否错过演员表?)
什么是C#语言设计师'这背后的推理?
答案 0 :(得分:10)
/
执行整数除法(5/3 = 1
)。要使它执行浮点除法,其中一个操作数必须是浮点(float
或double
)。这是因为有些情况下您的应用程序想要访问商或部门的其余部分(对于您使用的余数%
)。此外,整数除法比浮动除法更快。
另一方面,乘以浮点数总会返回一个浮点数。要将其保存为整数类型,您必须自己进行类型转换。浮点值在内存中具有不同的表示形式,也可能导致精度损失。
几乎所有的编程语言都是一样的:几乎所有编程语言都有整数除法和浮点除法,更常用的是同一个算子。几乎所有类型语言都需要从浮点到整数类型的转换。
答案 1 :(得分:5)
答案在C#文档中。在/
operator,它说
分割两个整数时,结果始终为整数。例如,7/3的结果是2。
乘法运算符没有这种行为,因此乘以double会产生一个double(整数可以在乘法之前隐式转换,因为它是一个加宽类型转换)。结果不能隐式转换,因为它将是一个缩小的类型转换。
答案 2 :(得分:4)
此问题与integer division无关。
这个问题就是为什么我可以做int / 2
而我无法做int * 0.5
。
int operator /(int x, int y);
这就是为什么可以做到的。
来自7.7.1 Multiplication operator
没有double * int
,反之亦然,只有double * double
和int * int
。由于没有从double
到int
的隐式转换,但存在从int
到double
的隐式转换,int
将转换为{{1} }}。这就是编译器实际做的事情。
答案 3 :(得分:2)
知道了。
Foo()
有效,因为操作中涉及的所有内容都是int
数据类型。
因此,编译器在进行计算时没有问题,因为所有类型都是int
类型,而mid
也是int
类型。所以编译器没有问题。
为了证明我的观点,如果你这样做,同样的Foo()
将不起作用:
void Foo(int start, int end)
{
int mid = (start + end) / 2.0;
}
因为,现在2.0
是双倍的,并且计算在int
+ int
/ double
之间,并且无法保证计算中的返回数字为{{ 1}}。
int
正在进行整数除法,而Foo()
正在进行浮点乘法