在 C# 中转换为“int”时,“const float”值与“float”不同
-
21-12-2019 - |
题
你们中的任何人都可以解释为什么会发生这种情况吗?
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();
}
解决方案
这个“为什么”基本上可以归结为这样一个事实:当与 float
数据,可以使用比指定的精度更高的内部表示 float
或者 double
. 。虚拟执行系统 (VES) 规范(第 12 节)明确满足了这一点 分区一):
浮点数使用内部浮点类型表示。在每个这样的实例中,变量或表达式的标称类型是
float32
或者float64
, ,但它的价值可以在内部用额外的范围和/或精度表示
然后我们有:
使用更广泛的内部表示
float32
或者float64
当开发人员对其代码看似无关的修改时,可能会导致计算结果差异,其结果可能是从内部表示(例如,在寄存器中)溢出到堆栈上的位置的值。
现在,根据 C#语言规范:
常量表达式的编译时求值使用与非常量表达式的运行时求值相同的规则,不同之处在于运行时求值会引发异常,而编译时求值会导致发生编译时错误。
但正如我们在上面观察到的,这些规则实际上有时允许使用更高的精度,并且何时使用这种增强的精度实际上并不在我们的直接控制之下。
显然,在不同的情况下,结果可能与您观察到的完全相反 - 编译器可能会降低到较低的精度,而运行时可能会保持较高的精度。
其他提示
我不能说这是一个重复的问题,因为这里是 - > Eric Postpischil评论
解释了关于int的和const int的一些非常相似的东西。
主要思想是,在生成代码而不是运行时,由编译器计算的两个常量的划分,但在该特定情况下,只要编译器就完成它,它会在 double 格式。因此,Xscalesizec基本上等于34.9999 ......所以当它在运行时浇铸到int时它变成了34。