除以 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# 语言设计者对此背后的推理是什么?

除以 2 vs 乘以 0.5

/进行整数除法(5/3 = 1)。要使它做浮点除法,其中一个操作数必须是浮点数(floatdouble)。这是因为在某些情况下,您的应用程序想要访问除法的商或余数(对于余数,您使用 % )。此外,整数除法比浮点除法更快。

另一方面,乘以浮点数总是

会返回浮点数。要将其保存为整数类型,您必须自己进行类型转换。浮点值在内存中具有不同的表示形式,还可能导致精度损失。

这在几乎所有编程语言中都是相同的:几乎所有编程语言都有整数除法和浮点除法,更经常使用相同的运算符。几乎所有类型化语言都需要从浮点类型转换为整型类型。

答案在 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 * doubleint * int.由于没有从 doubleint 的隐式转换,但存在从 intdouble 的隐式转换,因此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()在做浮点乘法