Unity:

MSVS:

so math error will accumulating
how to deal with it ?
Unity:

MSVS:

so math error will accumulating
how to deal with it ?
and how to explain this?
Unity:

but in MSVC no problem
Math error always accumulates when working with floats.
Now⌠the error you demonstrate here would only matter if you were passing binary data between unity and⌠MSVS. Iâm assuming thatâs microsoft visual studio⌠in which case you mean the MS .net runtime⌠so itâs mono vs .net runtimes, not unity vs msvs.
And yeah⌠when would you be passing data between the 2?
Huh?
Explain what? A return line? No problem in MSVC? Whatâs MSVC??? Visual Code? Why so many disparate names going on here???
Also, you can use code tags when showing us code:
Instead of uploading screencaps.
You generally shouldnât do exact equality operations on floats because they are prone to rounding errors. Instead you can use Mathf.Approximately() - Unity - Scripting API: Mathf.Approximately
what rounding errors in this case ?
x and x2 wonât be equal. You took a double, stuck it in a float (less discrete space for storage), then expanded it back out to a double.
You lost information.
You donât magically get information back because you convert back to a double.
What the hell? Use code tags. Have some respect for forum users or Iâll lock this thread.
Never use screenshots for code.
Short answer: Itâs complicated and floats are a mess, so just donât use equality with them, always use Mathf.Approximately.
For a longer answer, look at the responses to this person who noticed the same problem:
http://answers.unity3d.com/questions/121304/c-floating-point-confusion.html
Itâs not quite that simple⌠x is a double that is just a cast of the float on the right side to a double (note the âFâ in the number, which means the right hand side is a float). x2 is a cast of the same exact float to a double, except it goes through the intermediate step of being assigned a variable (fx2) before it is cast. So in theory, they should be the same - they are the same float value both cast to a double. But you canât trust floats even if they seem like they should be identical.
Good point, overlooked that the first one is a float divided by 7.
But yeah, float error collects over every operation. OP calculates x and x2 differently⌠so theyâre not going to be equal.
You typically donât need to. The accumulation error from floating point operations is typically so small that its not worth worrying about. Floats tend to loose precision after about 8 or 9 digits. If you consider a timer running at 60 frames per second, the maximum possible error accumulation is about one hundredth of a second across a full day. Using an approximation instead of an equality is more then enough to deal with this. In a multiplayer situation you simply force the players to match each other at regular intervals.
Where floats will kill you is their floating nature. Adding a small float to a large float has no effect*. This means that a simple timer running at 60 FPS in Unity will fail after about 2.5 days. And physics breaks down when you get too far from the origin. And so on. There are dozens of threads talking about ways to approach solving this problem.
*Formally stated it sounds like this: if a < b * 10 ^ -8 then a + b = b.
I post screenshot as proof of breakpoint.
I think this is bug, because unity have different behaviour than MSVS in same code

Itâs not a bug.
its a bug
same cast in both lines.
First result of divide is FLOAT and placed to double (x)
Second result of divide is FLOAT and placed to FLOAT (fx2) and then placed to double (x2).
So variables must be identical, and they are identical in MS .NET, but not in Unity.
If you even so much as look at a float, it might change.
Never ever assume that two floats are equal, unless you explicitly assigned them. And maybe not even then (depending on what you tried to assign to them). See Kiwasiâs last post.
I wouldnât call it a bug.
Iâd call it a difference in how the mono compiler and the .net compiler work.
NOTE - mono and .net are independent of one another. There is no one right way to compile C# to CIL. Each implementation may approach similar problems in different ways.
The problem youâre seeing here has to do with how Visual Studio compiles your code, and how Unity compiles your code.
Unityâs compiler aggressively optimizes trivial code. Where as the .net compiler does not.
Case in point here is code I wrote in both Visual Studio and Unity:
Visual Studio:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Console01
{
class Program
{
static void Main(string[] args)
{
if(Foo())
{
Console.WriteLine("NOT EQUAL");
}
Console.ReadLine();
}
static bool Foo()
{
double a = 3.14159274f / 7;
float x = 3.14159274f / 7;
double b = (double)x;
return a != b;
}
}
}
Unity:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class zTest01 : MonoBehaviour {
// Use this for initialization
void Start () {
if (Foo())
{
Debug.Log("NOT EQUAL");
}
}
static bool Foo()
{
double a = 3.14159274f / 7;
float x = 3.14159274f / 7;
double b = (double)x;
return a != b;
}
}
Now, I built both, and then decompiled them using Dotpeek:
The CIL for just the Foo method:âŚ
Visual Studio:
.method private hidebysig static bool
Foo() cil managed
{
.maxstack 2
.locals init (
[0] float64 a,
[1] float32 x,
[2] float64 b,
[3] bool V_3
)
// [22 9 - 22 10]
IL_0000: nop
// [23 13 - 23 40]
IL_0001: ldc.r8 0.448798954486847
IL_000a: stloc.0 // a
// [25 13 - 25 39]
IL_000b: ldc.r4 0.448799
IL_0010: stloc.1 // x
// [26 13 - 26 34]
IL_0011: ldloc.1 // x
IL_0012: conv.r8
IL_0013: stloc.2 // b
// [28 13 - 28 27]
IL_0014: ldloc.0 // a
IL_0015: ldloc.2 // b
IL_0016: ceq
IL_0018: ldc.i4.0
IL_0019: ceq
IL_001b: stloc.3 // V_3
IL_001c: br.s IL_001e
// [29 9 - 29 10]
IL_001e: ldloc.3 // V_3
IL_001f: ret
} // end of method Program::Foo
Unity:
.method private hidebysig static bool
Foo() cil managed
{
.maxstack 2
.locals init (
[0] float64 V_0,
[1] float32 V_1,
[2] float64 V_2
)
// [20 5 - 20 51]
IL_0000: ldc.r8 0.448798963001796
IL_0009: stloc.0 // V_0
IL_000a: ldc.r4 0.448799
IL_000f: stloc.1 // V_1
IL_0010: ldloc.1 // V_1
IL_0011: conv.r8
IL_0012: stloc.2 // V_2
IL_0013: ldloc.0 // V_0
IL_0014: ldloc.2 // V_2
IL_0015: ceq
IL_0017: ldc.i4.0
IL_0018: ceq
IL_001a: ret
} // end of method zTest01::Foo
Youâll notice the âFooâ code is distinctly different in both. This is because Unity recognized the code is really a bunch of constants and so pre-calculated the arithmetic of said constants. Where as the Visual Studio .net compiler did not optimize at all instead of allowing the code to remain mostly identical:
Visual Studio:
static bool Foo()
{
double a = 3.14159274f / 7;
float x = 3.14159274f / 7;
double b = (double)x;
return a != b;
}
Unity:
private static bool Foo()
{
return 0.448798963001796 != 0.448798954486847;
}
It appears the Unity compiler favors its internal double floating point implementation rather than the .net implementation.
It also appears that it did the double to float back to double truncation for âbâ, but directly double to double (ignore the âFâ on the constant) for âaâ. (note that a, or left, is more accurate than b, or right. This says to me that b was truncated, and then coerced back into a double by the compiler)
This isnât a bug⌠since the floating point standard does not require the implementation to be accurate from machine to machine, runtime to runtime. Itâs the inherent design of floats⌠favoring speed/efficiency over reproducibility.
This is something you must always be aware of when dealing with floats.
If you need better accuracy using a fixed-point numeric type. Or the built in âdecimalâ type.
Though still compiler differences may still arise like this here. Which again, is NOT a bug. There is no rule saying compilers must produce identical machine code (or intermediate code in the case of CIL).
Now⌠if you want to insist itâs a bug.
Then weâre going to get into semantics on a pedantic level.
And in the end⌠it doesnât matter.
Cause itâs a bug that would be considered acceptable by both Unity and Microsoft, and thusly will not be changed (well it could change, but it wonât be changed to remedy your perceived issue⌠rather just because compilers change over time). And instead should just be something you as a developer shoulld be aware of. As it falls under the whole ânever trust a float to be 100% accurateâ.
So regardless of if you want to call it a bug or just implementation differences⌠the end result is the same. DO NOT TRUST FLOATS.
Here is another puzzle. Itâs for Visual Studio, I havenât tested it in Unity.
using System;
class Program
{
private static float sa, sb;
public static void Main()
{
Console.WriteLine(Multiply(10f, .1f) == Multiply(10f, .1f));
var la = Multiply(10f, .1f);
var lb = Multiply(10f, .1f);
Console.WriteLine(la == lb);
sa = Multiply(10f, .1f);
sb = Multiply(10f, .1f);
Console.WriteLine(sa == sb);
Console.ReadLine();
}
private static float Multiply(float x, float y) => x * y;
}
The output depends on the configuration:
Can anyone come up with an explanation? Thereâs a hint inside.