I have the following code:

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

I am expecting “intvar” to always be equal to “z” in the loop, however after 31 iterations there is some kind of rounding error and when z=32 intvar = 33, instead of z=32 intvar =32

from then onwards intvar is always off by 1, so for z<32 intvar=z and for z >31 intvar=z+1

my intended result is for z = intvar always, I dont understand why this arbitrarily changes when z reaches 32, I would appreciate it if someone could help me, Thanks in advance.

## Answer

I took your code and translated them from Unity to the .NET Framework. This involved changing `Mathf.FloorToInt(someFloat)`

to `(int)Math.Floor(someFloat)`

and `Mathf.Floor(ValueToSnap)`

to `(float)Math.Floor(ValueToSnap)`

. I believe it does the same thing, but it takes a detour through `double`

.

I also inserted a WriteLine statement in your loop:

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

I see the same behaviour.

In particular, I see breaks at `z`

== 9:

FloatVar: 8.499999 Z: 8 IntVar: 8 FloatVar: 9.499999 Z: 9 IntVar: 9 FloatVar: 10.5 Z: 10 IntVar: 10 FloatVar: 11.5 Z: 11 IntVar: 11

and at `z`

== 32:

FloatVar: 30.5 Z: 30 IntVar: 30 FloatVar: 31.5 Z: 31 IntVar: 31 FloatVar: 32.5 Z: 32 IntVar: 33 FloatVar: 33.5 Z: 33 IntVar: 34

Even if I extend the precision of the output beyond the precision of the float:

Debug.WriteLine($"FloatVar: {floatvar:0.0000000000000000000} Z: {z} IntVar: {intvar}");

I see the same behaviour, rounding down below 32 and rounding up above it.

Then I greatly simplified your calculation:

floatvar2 = z + 0.499999f; intvar2 = (int)SnapValueToCoreBlock(floatvar2);

And I still see the same behaviour.

So, what it seems is that:

anInteger + 0.499999f + 0.5f;

is less than `anInteger + 1.0f`

for values of `anInteger < 32`

and equal to or greater than `anInteger + 1.0f`

for values `anInteger >= 32`

. And, you know what, that doesn’t surprise me. You are right at the edge of floating point precision (remember, floats have ~6-9 digits of precision: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types). When you went from 31 to 32, you ended up setting another bit, and that’s what likely made the difference.

**Final Comment** *(as an update)*

You say *“the 0.4999999 is a variable that I am using for collisions”*. You need to read up on how to compare floating point values, and how to properly use an *epsilon*. Here’s one thing I found (https://bitbashing.io/comparing-floats.html). It’s C++ focused, but seems to address the issues. As a final comment, if you are ever using measured values (like in a chemical process control system), you need to include the precision of your measurements in the establishment of an *epsilon*.