为什么 (int)==(float) 总是编译为 (float)==(float)
Why (int)==(float) always compiles to (float)==(float)
我正在研究 C# 编译器并试图了解数学运算规则。
我发现 ==
运算符在两种不同的原始类型之间存在难以理解的行为。
int a = 1;
float b = 1.0f;
Console.WriteLine(a == b);
这实际上编译为
.locals init (
[0] int32,
[1] float32
)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.0
IL_0003: ldc.r4 1
IL_0008: stloc.1
IL_0009: ldloc.0
IL_000a: conv.r4
IL_000b: ldloc.1
IL_000c: ceq
这意味着
(float)a == (float)b
我的期望是 (int)a == (int)b
,因为左值是 integer
。
这个结果有什么原因吗?
- 这是我的猜测:
int->float
比 float->int
快
这实际上与 speed(正如您所建议的)无关,而与 Implicit Conversions 更多相关,您可以找到在 C# Specifications
中 Numeric Promotions 主题下定义的相关信息
12.4.7 Numeric promotions
Numeric promotion consists of automatically performing certain
implicit conversions of the operands of the predefined unary and
binary numeric operators. Numeric promotion is not a distinct
mechanism, but rather an effect of applying overload resolution to the
predefined operators. Numeric promotion specifically does not affect
evaluation of user-defined operators, although user-defined operators
can be implemented to exhibit similar effects.
As an example of numeric promotion, consider the predefined
implementations of the binary * operator:
int operator *(int x, int y);
uint operator *(uint x, uint y);
long operator *(long x, long y);
ulong operator *(ulong x, ulong y);
float operator *(float x, float y);
double operator *(double x, double y);
decimal operator *(decimal x, decimal y);
When overload resolution rules (§12.6.4) are applied to this set of operators, the effect is to select the first of the operators for
which implicit conversions exist from the operand types.
更多
Binary numeric promotion occurs for the operands of the predefined +
,
–
, *
, /
, %
, &
, |
, ^
, ==
, !=
, >
, <
, >=
, and <=
binary operators.
Binary numeric promotion implicitly converts both operands to a common
type which, in case of the non-relational operators, also becomes the
result type of the operation. Binary numeric promotion consists of
applying the following rules, in the order they appear here:
- If either operand is of type decimal, the other operand is converted to type decimal, or a bindingtime error occurs if the other operand is
of type float or double.
- Otherwise, if either operand is of type double, the other operand is converted to type double.
- Otherwise, if either operand is of type float, the other operand is converted to type float.
- Otherwise, if either operand is of type ulong, the other operand is converted to type ulong, or a binding-time error occurs if the other
operand is of type sbyte, short, int, or long.
- Otherwise, if either operand is of type long, the other operand is converted to type long.
- Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int, both operands are converted to type
long.
- Otherwise, if either operand is of type uint, the other operand is converted to type uint.
- Otherwise, both operands are converted to type int.
你可以通过他们展示的例子来感受一下
byte b = 1;
short a = 2;
WriteLine((int)b==(int)s); // promotes both to int
int i = 1;
double d = 2;
WriteLine((double)i==d); // promotes i to double
或者你的例子
int a = 1;
float b = 1.0f;
WriteLine((float)a==b); // promotes a to float
我正在研究 C# 编译器并试图了解数学运算规则。
我发现 ==
运算符在两种不同的原始类型之间存在难以理解的行为。
int a = 1;
float b = 1.0f;
Console.WriteLine(a == b);
这实际上编译为
.locals init (
[0] int32,
[1] float32
)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.0
IL_0003: ldc.r4 1
IL_0008: stloc.1
IL_0009: ldloc.0
IL_000a: conv.r4
IL_000b: ldloc.1
IL_000c: ceq
这意味着
(float)a == (float)b
我的期望是 (int)a == (int)b
,因为左值是 integer
。
这个结果有什么原因吗?
- 这是我的猜测:
int->float
比float->int
快
这实际上与 speed(正如您所建议的)无关,而与 Implicit Conversions 更多相关,您可以找到在 C# Specifications
中 Numeric Promotions 主题下定义的相关信息12.4.7 Numeric promotions
Numeric promotion consists of automatically performing certain implicit conversions of the operands of the predefined unary and binary numeric operators. Numeric promotion is not a distinct mechanism, but rather an effect of applying overload resolution to the predefined operators. Numeric promotion specifically does not affect evaluation of user-defined operators, although user-defined operators can be implemented to exhibit similar effects.
As an example of numeric promotion, consider the predefined implementations of the binary * operator:
int operator *(int x, int y); uint operator *(uint x, uint y); long operator *(long x, long y); ulong operator *(ulong x, ulong y); float operator *(float x, float y); double operator *(double x, double y); decimal operator *(decimal x, decimal y);
When overload resolution rules (§12.6.4) are applied to this set of operators, the effect is to select the first of the operators for which implicit conversions exist from the operand types.
更多
Binary numeric promotion occurs for the operands of the predefined
+
,–
,*
,/
,%
,&
,|
,^
,==
,!=
,>
,<
,>=
, and<=
binary operators. Binary numeric promotion implicitly converts both operands to a common type which, in case of the non-relational operators, also becomes the result type of the operation. Binary numeric promotion consists of applying the following rules, in the order they appear here:
- If either operand is of type decimal, the other operand is converted to type decimal, or a bindingtime error occurs if the other operand is of type float or double.
- Otherwise, if either operand is of type double, the other operand is converted to type double.
- Otherwise, if either operand is of type float, the other operand is converted to type float.
- Otherwise, if either operand is of type ulong, the other operand is converted to type ulong, or a binding-time error occurs if the other operand is of type sbyte, short, int, or long.
- Otherwise, if either operand is of type long, the other operand is converted to type long.
- Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int, both operands are converted to type long.
- Otherwise, if either operand is of type uint, the other operand is converted to type uint.
- Otherwise, both operands are converted to type int.
你可以通过他们展示的例子来感受一下
byte b = 1;
short a = 2;
WriteLine((int)b==(int)s); // promotes both to int
int i = 1;
double d = 2;
WriteLine((double)i==d); // promotes i to double
或者你的例子
int a = 1;
float b = 1.0f;
WriteLine((float)a==b); // promotes a to float