0

I remarked a surprising behavior in one of my C# functions in Unity. A float passed to my function takes an extraordinary value inside it.

I know floats can go weird when used with numbers with a lot of decimals, but in that case it only happens inside the function. I also tried with doubles and the results are similar.

private float i = 0;
private float whatever1 = Random.Range(1f, 10f);//Some value in 1-10 range
private float whatever2 = Random.Range(1f, 10f);//Some value in 1-10 range
private float MyFunc(float j)
{
    Debug.Log(j.ToString());
    float max = whatever1 > whatever2 ? whatever1 : whatever2;
    return j - max;
}

public void Update(){
    i += Random.Range(1/60f, 1/50f);
}

public void Test(){
    Debug.Log(i);
    MyFunc(i);
    MyFunc(67f);
}


// 10.256463
// 4,622506E+18
// 4,622506E+18

So I tried debugging and logging the value of i and j. Its value is correct outside of MyFunc, but becomes a weird 4.16E+18 as soon as it enters the function.

I've tried several things so far :

  • using Mathf.Max instead of a ternary operator
  • using doubles instead of floats
  • passing a constant to the function instead of a value (see MyFunc(67))
  • rebuilding the solution/project

The result :

For a value of i in the 9-15 range, j has a value between 4,0E+18 and 6,.0E+18 j takes that weird value before MyFunc makes any operation on the float. So it doesn't seem related to floating point arithmetic issues.

I ended up inlining the content of the function wherever I needed it, but I still don't understand what happens. Can you explain ?

monsieur_h
  • 1,360
  • 1
  • 10
  • 20
  • 3
    Possible duplicate of [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – MakePeaceGreatAgain Apr 24 '17 at 14:40
  • I thought so, and read that exact question. I would understand if the change was hapenning when making an operation on the float. But the change happens **when passed to the function**. – monsieur_h Apr 24 '17 at 14:44
  • This means the same, as any floating-point number can´t be stored exactly (or at least not every one can be). Thus even the assignment `float a = 0.1` is internally **stored** as `a` being something like `0.9999999999999993` or so. This inaccuracy happens whenever you store any number in a floating-point-number, no matter if you actually *do* some calculation on it. – MakePeaceGreatAgain Apr 24 '17 at 14:48
  • ... and since `float` are passed by value, you mean that it is the assignment to the local-scope float that breaks the value ? – monsieur_h Apr 24 '17 at 14:52
  • Also I don't understand why `i+= Time.deltaTime` doesn't produce the issue, while going into the function triggers the loss of value. (100% reproducible) – monsieur_h Apr 24 '17 at 14:57
  • I don´t know what `Time.Deltatime` is, but I assume it effectly returns only integers that are completely representable by floating-point numbers. This is because all floating-point numbers are internally stored as powers of `2`. This implies that every intereger can be represented as power of 2 (e.g. `4 = 1 * 2 ^ 2 + 0 * 2 ^1 + 0 * 2 ^ 0`, `3 = 2 ^1 + 2 ^ 0`). The same does however not apply to decimals. – MakePeaceGreatAgain Apr 24 '17 at 15:13
  • 2
    What is `matchEnd`? – Kyle Apr 24 '17 at 15:17
  • @Kyle It's actually `j` in the original code. Thank you for noticing it, I edited my questions. – monsieur_h Apr 24 '17 at 15:34
  • 1
    @monsieur_h Now replace `Time.deltaTime` with an appropriate runtime value (such as `1/60f` for a frame time at 60 frames per second) as well as `whateverx` then we'll have a [mcve example](https://stackoverflow.com/help/mcve). – Quantic Apr 24 '17 at 15:55
  • @Quantic Done. I should've thought of it myself though. – monsieur_h Apr 24 '17 at 16:07
  • What is `Random.Range`, I cannot find that method in C#. – Chris Dunaway Apr 24 '17 at 18:28
  • It's specific to Unity – monsieur_h Apr 25 '17 at 07:33

0 Answers0