Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么这个公式在31次循环后会中断?_C#_Unity3d_Math_Floating Point_Formula - Fatal编程技术网

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;