除以 2 vs 乘以 0.5
本文关键字:乘以 vs 除以 | 更新日期: 2023-09-27 17:57:02
请考虑以下事项:
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
:
不能将类型'double隐式转换为int。显式转换 存在(你缺少演员表吗?
C# 语言设计者对此背后的推理是什么?
/
进行整数除法(5/3 = 1
)。要使它做浮点除法,其中一个操作数必须是浮点数(float
或double
)。这是因为在某些情况下,您的应用程序想要访问除法的商或余数(对于余数,您使用 %
)。此外,整数除法比浮点除法更快。
会返回浮点数。要将其保存为整数类型,您必须自己进行类型转换。浮点值在内存中具有不同的表示形式,还可能导致精度损失。
这在几乎所有编程语言中都是相同的:几乎所有编程语言都有整数除法和浮点除法,更经常使用相同的运算符。几乎所有类型化语言都需要从浮点类型转换为整型类型。
答案在 C# 文档中。在/
运算符上,它说
乘法将两个整数相除时,结果始终为整数。例如,7/3的结果是2。
运算符没有这种行为,因此乘以双精度会产生双精度(整数可以在乘法之前隐式强制转换,因为它是扩展类型转换)。结果不能隐式转换,因为它将是缩小类型转换。
这个问题与整数除法无关。
这个问题都是关于为什么我可以做int / 2
但我不能做int * 0.5
.
从7.7.2 Division operator
int operator /(int x, int y);
这就是为什么可以这样做的原因。
从7.7.1 Multiplication operator
没有double * int
,反之亦然,只有double * double
和int * int
.由于没有从 double
到 int
的隐式转换,但存在从 int
到 double
的隐式转换,因此int
将转换为 decimal
。这就是编译器实际所做的。
知道了。
Foo()
工作是因为操作中涉及的所有内容都是int
数据类型。
因此,编译器在进行计算时不会有问题,因为所有类型都是int
类型,并且mid
也是int
类型。所以编译器不会有问题。
为了证明我的观点,如果您这样做,相同的Foo()
将不起作用:
void Foo(int start, int end)
{
int mid = (start + end) / 2.0;
}
因为,现在2.0
是双精度,计算在 int
+ int
/double
之间,并且不能保证计算返回的数字是int
.
Foo()
在做整数除法,而Bar()
在做浮点乘法