& # 39; const浮动# 39;值与'float'当转换为'int'在c#

本文关键字:int 转换 float const 浮动 值与 | 更新日期: 2023-09-27 18:06:19

有人能解释一下为什么会这样吗?

static void Main()
{
    const float xScaleStart = 0.5f;
    const float xScaleStop = 4.0f;
    const float xScaleInterval = 0.1f;
    const float xScaleAmplitude = xScaleStop - xScaleStart;
    const float xScaleSizeC = xScaleAmplitude / xScaleInterval;
    float xScaleSize = xScaleAmplitude / xScaleInterval;
    Console.WriteLine(">const float {0}, (int){1}", xScaleSizeC, (int)xScaleSizeC);
    Console.WriteLine(">      float {0}, (int){1}", xScaleSize, (int)xScaleSize);
    Console.ReadLine();
}
输出:

>const float 35, (int)34
>      float 35, (int)35

我知道0.1的二进制表示实际上是0.09999990463256835937,尽管为什么使用'const float'而不是'float'会发生这种情况?这被认为是一个编译器错误吗?

对于记录,代码编译成:

private static void Main(string[] args)
{
    float xScaleSize = 35f;
    Console.WriteLine(">const float {0}, (int){1}", 35f, 34);
    Console.WriteLine(">      float {0}, (int){1}", xScaleSize, (int)xScaleSize);
    Console.ReadLine();
}

& # 39; const浮动# 39;值与'float'当转换为'int'在c#

这基本上归结为这样一个事实,即在处理float数据时,可能经常使用比floatdouble指定的精度更高的内部表示。这在虚拟执行系统(VES)规范(分区I的第12节)中得到了明确的满足:

浮点数用内部浮点数表示类型。在每个这样的实例中,变量或表达式的名义类型要么是float32,要么是float64值可以用额外的范围和/或精度在内部表示

然后是:

使用比float32float64宽的内部表示会导致当开发人员对其代码进行看似无关的修改时,计算结果这可能是一个值从内部表示(例如,在寄存器中)溢出到堆栈。

现在,根据c#语言规范:

常量表达式的编译时求值使用与非常量表达式的运行时求值相同的规则,除了在运行时求值会抛出异常的地方,编译时求值会导致编译时错误发生。

但是正如我们上面所看到的,规则实际上允许在某些时候使用更高的精度,而当使用这种增强的精度时,实际上并不在我们的直接控制之下。


显然,在不同的情况下,结果可能与您所观察到的完全相反——编译器可能会降低精度,而运行时可能会保持更高的精度。

我不能说这是一个重复的问题,因为在这里-> Eric postischil评论

对int型和const型的解释非常相似。

主要思想是编译器在生成代码之前计算两个常量的除法,而不是在运行时计算,但是在这个特定的情况下,每当编译器这样做时,它都会以double格式执行计算。因此xScaleSizeC基本上等于34.9999…所以当它在运行时被转换为int时它就变成了34