从int转换为float的问题

Cod*_*ber 13 c# floating-point

有一种我无法理解的奇怪行为.同意浮点数是近似值,因此即使显然返回没有十进制数的数的运算也可以近似为带小数的运算.

我这样做:

int num = (int)(195.95F * 100);
Run Code Online (Sandbox Code Playgroud)

因为它是一个浮点运算,我得到19594而不是19595 ..但这是正确的.

令我困惑的是,如果我这样做

float flo = 195.95F * 100;
int num = (int) flo;
Run Code Online (Sandbox Code Playgroud)

我得到19595的正确结果.

知道为什么会这样吗?

Mar*_*ell 11

我查看这是否是编译器正在进行数学计算,但即使你强行执行它也会这样:

static void Main()
{
    int i = (int)(GetF() * GetI()); // 19594
    float f = GetF() * GetI();
    int j = (int)f; // 19595
}
[MethodImpl(MethodImplOptions.NoInlining)]
static int GetI() { return 100; }
[MethodImpl(MethodImplOptions.NoInlining)]
static float GetF() { return 195.95F; }
Run Code Online (Sandbox Code Playgroud)

看起来差别在于它是否保留在寄存器中(比正常的r4宽)或者被强制float变量:

L_0001: call float32 Program::GetF()
L_0006: call int32 Program::GetI()
L_000b: conv.r4 
L_000c: mul 
L_000d: conv.i4 
L_000e: stloc.0 
Run Code Online (Sandbox Code Playgroud)

VS

L_000f: call float32 Program::GetF()
L_0014: call int32 Program::GetI()
L_0019: conv.r4 
L_001a: mul 
L_001b: stloc.1 
L_001c: ldloc.1 
L_001d: conv.i4 
L_001e: stloc.2 
Run Code Online (Sandbox Code Playgroud)

唯一的区别是stloc.1/ ldloc.1.

这得到以下事实的支持:如果你进行优化构建(将删除局部变量),我得到两者的相同答案(19594).