C#:将带有浮点数的表达式转换为 int 时的错误结果

C#: Wrong result when converting expression with floats to int

取下面的代码:

float a = 100.0f;
float b = 0.05f;

如果我想将ab相除的结果转换为一个整数,我可以用这个代码来完成:

float c = a / (b * 1000.0f); // c = 2f
int res = (int)c; // res = 2

但是我想减少代码行数,所以我更喜欢使用这段代码:

int res = (int)(a / (b * 1000.0f)); // Here we are --> res = 1 !

为什么最后一个代码我得到的是 res = 1 而不是 res = 2

编译器在计算某些表达式时使用额外的精度。在 C# language specification 中,条款 9.3.7 允许实现在浮点表达式中使用比结果类型更高的精度:

Floating-point operations may be performed with higher precision than the result type of the operation.

注意.05f的值为0.0500000007450580596923828125。当以 float 精度计算 .05f * 1000.0f 时,由于四舍五入,结果为 50。但是,当以 double 或更高精度计算时,结果为 50.0000007450580596923828125。然后用 double 精度除以 100 得到 1.999999970197678056393897350062616169452667236328125。当这个转换为int时,结果是1.

float c = a / (b * 1000.0f);中,除法的结果转为float。即使以 double 精度计算除法并产生 1.999999970197678056393897350062616169452667236328125,此值在舍入为 float 时变为 2,因此 c 设置为 2。

int res = (int)(a / (b * 1000.0f));中,除法结果不转换为float。如果编译器以 double 精度计算它,则结果为 1.999999970197678056393897350062616169452667236328125,转换结果为 1.