C# 为什么这个公式在31次循环后会中断?
我有以下代码:C# 为什么这个公式在31次循环后会中断?,c#,unity3d,math,floating-point,formula,C#,Unity3d,Math,Floating Point,Formula,我有以下代码: public float SnapValueToCoreBlock(float ValueToSnap) { ValueToSnap = ValueToSnap + 0.5f; ValueToSnap = Mathf.Floor(ValueToSnap); return ValueToSnap; } float floatvar; int intvar; for (int z = 0; z < 100; z++) {
public float SnapValueToCoreBlock(float ValueToSnap)
{
ValueToSnap = ValueToSnap + 0.5f;
ValueToSnap = Mathf.Floor(ValueToSnap);
return ValueToSnap;
}
float floatvar;
int intvar;
for (int z = 0; z < 100; z++)
{
floatvar = z + (Mathf.FloorToInt(0.499999f) + 1) * 0.499999f / (Mathf.FloorToInt(0.499999f) + 1);
intvar = (int)SnapValueToCoreBlock(floatvar);
}
我希望intvar在循环中始终等于z,但是在31次迭代之后,会出现某种舍入错误,当z=32 intvar=33时,而不是z=32 intvar=32
从那时起,intvar总是以1关闭,因此对于z31 intvar=z+1
我的预期结果是z=intvar始终,我不明白为什么当z达到32时会发生任意变化,如果有人能帮助我,我将不胜感激,提前谢谢。我将您的代码从Unity翻译到.NET Framework。这涉及将Mathf.FloorToIntsomeFloat更改为intMath.FloorsomeFloat,将Mathf.FloorValueToSnap更改为floatMath.FloorValueToSnap。我相信它也会做同样的事情,但它需要绕道双行 我还在循环中插入了WriteLine语句:
for (int z = 0; z < 100; z++)
{
floatvar = z + ((int)Math.Floor(0.499999f) + 1) * 0.499999f / ((int)Math.Floor(0.499999f) + 1);
intvar = (int)SnapValueToCoreBlock(floatvar);
Debug.WriteLine($"FloatVar: {floatvar} Z: {z} IntVar: {intvar}");
}
在z==32时:
即使我将输出精度扩展到浮点精度之外:
Debug.WriteLine($"FloatVar: {floatvar:0.0000000000000000000} Z: {z} IntVar: {intvar}");
我看到了同样的行为,在32以下四舍五入,在32以上四舍五入
然后我大大简化了你的计算:
floatvar2 = z + 0.499999f;
intvar2 = (int)SnapValueToCoreBlock(floatvar2);
我仍然看到同样的行为
所以,看起来是这样的:
anInteger + 0.499999f + 0.5f;
对于小于32的整数,小于整数+1.0f;对于大于等于32的整数,等于或大于整数+1.0f。你知道吗,这并不让我惊讶。您正处于浮点精度的边缘请记住,浮点精度约为6-9位:。当你从31岁到32岁时,你又设置了一个位子,这很可能是造成差异的原因
作为更新的最后评论
您说0.4999999是我用于碰撞的变量。您需要了解如何比较浮点值,以及如何正确使用epsilon。我发现了一件事。它是C++的重点,但似乎解决了这些问题。最后一点,如果您使用测量值(如化学过程控制系统中的测量值),则需要在建立ε时包含测量精度。可能是四舍五入问题,一旦达到32位,小数点位将强制将数字四舍五入。如果你到了64岁或是别的什么,是不是2岁?也许不用施法就可以测试你的值,看看你31号的值是多少,看看它是否会向上取整。对于64号,它的值仍然是1,所以z=64表示intvar=65,对于z=99,intvar=100,floatvar总是显示z.5,也就是说,对于z=1,floatvar=1.5,对于z=70,floatvar=70.5,我猜出了64,可能是70或80,或者,无论计算结果如何,当你投下它的时候,它都会被取整。我会调试并逐步查看第31次查看中的所有数字,然后查看其中一个是否会导致舍入问题。我仍然不确定这是否是一个问题,但由于您将浮点数转换为int,因此需要查看一些内容。如果您想使用浮点数,则不能使用0.49999f之类的数字。记住,浮点数只有6-9位数的精度,你有7位数。如果你有兴趣,我编辑了我的答案
floatvar2 = z + 0.499999f;
intvar2 = (int)SnapValueToCoreBlock(floatvar2);
anInteger + 0.499999f + 0.5f;