在C#中转换为“int”时,“const float”值与“float”不同

你们能解释为什么会发生这种事吗?

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的二进制表示forms实际上是0.09999990463256835937,但是为什么使用'const float'而不是'float'呢? 这被认为是一个编译器错误?

为了logging,代码编译成:

 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(); } 

这个“为什么”基本上归结为这样一个事实,即在处理float数据时,可能会使用比floatdouble更精确的内部表示。 这在虚拟执行系统(VES)规范( 分区I的第12节)中被明确地考虑到了:

浮点数用内部浮点types表示。 在每个这样的实例中,variables或expression式的标称types是float32float64 ,但是它的值可以用附加范围和/或精度在内部表示

然后,我们有:

使用比float32float64更宽的内部表示可能会导致计算结果的差异,当开发人员对其代码做出看似不相关的修改时,结果可能是内部表示溢出了一个值(例如,在注册)到堆栈上的位置。

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

常量expression式的编译时评估使用与非常量expression式的运行时评估相同的规则,除了运行时评估会引发exception,编译时评估会导致编译时错误发生。

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


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

我不能说这是一个重复的问题,因为在这里 – “ 埃里克Postpischil评论

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

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