Nic*_*ick 5 c# floating-point casting visual-studio-2015
------请跳到最后更新-----------
我发现了一个错误(在我的代码中),我正在努力找到正确的理解.
这一切都归结为在调试时从立即窗口获取的这个特定示例:
x
0.00023569075
dx
-0.000235702712
x+dx+1f < 1f
true
(float) (x+dx+1f) < 1f
false
Run Code Online (Sandbox Code Playgroud)
x和dx都是float类型.那么为什么当我进行演员表时布尔值会有所不同?
在我的实际代码中:
x+=dx
if( x+1f < 1f) // Add a one to truncate really small negative values (originally testing x < 0)
{
// do actions accordingly
// Later doing
x+=1; // Where x<1 has to be true, therefore we have to get rid of really small negatives where x+=1 will give x==1 as true and x<1 false.
}
Run Code Online (Sandbox Code Playgroud)
但我现在正在尝试与演员
x+=dx;
if( (float)( x+1f) < 1f) // Add a one to truncate really small negative values (originally testing x < 0)
{
// do actions accordingly
// Later doing
x+=1; // Where x<1 has to be true, therefore we have to get rid of really small negatives where x+=1 will give x==1 as true and x<1 false.
}
Run Code Online (Sandbox Code Playgroud)
视觉工作室说,演员是多余的,但如果没有它,它会得到一个错误的假设,因为立即窗口也告诉我:
x+dx+1f < 1f
true
Run Code Online (Sandbox Code Playgroud)
我目前正在运行我的代码,看看我是否再次使用演员来获取错误,并且一旦我确信无论如何我都会更新.
同时我希望有人可以理清这里发生的事情吗?我能指望演员做点什么吗?
更新 - 变量 我的变量x和dx是Vector2(Xna/monogame)的组件.所以在代码中你应该阅读
Vector2 coord; // the x (and y) components are floats.
Vector2 ds;
coord.X // where it says x
ds.X // where it says dx
Run Code Online (Sandbox Code Playgroud)
我认为这没关系,但也许确实如此.
更新2 - 删除上面的示例
看到演员确实改变了结果我做了这个简单的演示
class Program
{
static void Main(string[] args)
{
float a = -2.98023224E-08f; // Just a small negative number i picked...
Console.WriteLine(((a + 1f) < 1f) ? "true" : "false"); //true
Console.WriteLine(((float)(a + 1f) < 1f) ? "true":"false"); //false
// Visual Studio Community 2015 marks the above cast as redundant
// but its clearly something fishy going on!
Console.Read();
}
}
Run Code Online (Sandbox Code Playgroud)
那么,即使VS说它是多余的,为什么这个演员会改变结果呢?
我认为 C# 规范的重要部分是:
“浮点运算可以以比运算结果类型更高的精度执行。例如,某些硬件架构支持“扩展”或“长双精度”浮点类型,其范围和精度比双精度类型更大,并且使用这种更高精度类型隐式执行所有浮点运算。只有在性能方面付出过高的代价,此类硬件架构才能以较低的精度执行浮点运算,而不是要求实现同时丧失性能和精度,C# 允许用于所有浮点运算的更高精度类型。” - https://msdn.microsoft.com/en-us/library/aa691146(v=vs.71).aspx
通过查看这三行代码,并以略有不同的方式进行比较,我们可以推断出这几乎肯定是正在发生的事情:
float a = -2.98023224E-08f;
Console.WriteLine((a + 1f) < 1f); // True
Console.WriteLine((float)(a + 1f) < 1f); //False
Console.WriteLine((double)(a + 1f) < 1f); //True
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,第一个计算的结果(这就是我们想知道的)与中间值被转换为双精度值相同,告诉我们编译器正在利用在 a 处执行计算的选项。更高的精度。
当然,结果不同的原因是,虽然我们可以看出,当计算a+1f结果为1时,结果应该是true,因此比较是false。
为了将上面的结果四舍五入,a将其存储在指数为 -25 且分数为 0 的浮点数中。如果向其中添加 1,则 -25 指数部分太小而无法表示,因此需要舍入和在这种情况下,四舍五入后的数字为 1。这是因为单精度浮点数的存储方式,前导 1 后面的部分只有 23 位,因此没有精度来存储小数,因此结束存储时将其向上舍入为 1。因此,为什么当我们强制它一直使用浮点计算时,比较会返回 false。
| 归档时间: |
|
| 查看次数: |
121 次 |
| 最近记录: |