Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Float math issue

Discussion in 'Scripting' started by Velth, Feb 20, 2018.

  1. Velth

    Velth

    Joined:
    Feb 20, 2018
    Posts:
    4
    Hi all,

    Version 2017.3.0p4 (25a5860ad58d) Personal

    I have some trouble with float variables, after some tests I made this really simple script to check the issue:

    Code (CSharp):
    1.  
    2.     public float testmath;
    3.  
    4.     void Start()
    5.     {
    6.         print("TEST 1");
    7.         testmath = 0f;
    8.         print("testmath start = " + testmath);
    9.         testmath = testmath + 0.6f;
    10.         print("testmath add = " + testmath);
    11.         testmath = testmath - 0.6f;
    12.         print("testmath sub = " + testmath);
    13.  
    14.         print("TEST 2");
    15.         testmath = 0f;
    16.         print("testmath start = " + testmath);
    17.         testmath = testmath + 0.2f;
    18.         print("testmath add = " + testmath);
    19.         testmath = testmath - 0.2f;
    20.         print("testmath sub = " + testmath);
    21.  
    22.         print("TEST 3");
    23.         testmath = 0f;
    24.         print("testmath start = " + testmath);
    25.         testmath = testmath + 0.2f + 0.2f;
    26.         print("testmath add = " + testmath);
    27.         testmath = testmath - 0.2f - 0.2f;
    28.         print("testmath sub = " + testmath);
    29.  
    30.         print("TEST 4");
    31.         testmath = 0f;
    32.         print("testmath start = " + testmath);
    33.         testmath = testmath + 0.2f + 0.2f + 0.2f;
    34.         print("testmath add = " + testmath);
    35.         testmath = testmath - 0.2f - 0.2f - 0.2f;
    36.         print("testmath sub = " + testmath);
    37.  
    38. }
    39.  
    Results:
    TEST 1
    testmath start = 0
    testmath add = 0.6
    testmath sub = 0

    TEST 2
    testmath start = 0
    testmath add = 0.2
    testmath sub = 0

    TEST 3
    testmath start = 0
    testmath add = 0.4
    testmath sub = 0

    TEST 4
    testmath start = 0
    testmath add = 0.6
    testmath sub = 1.490116E-08

    0.2 is not the magic number with this issue happen, I also found an issue with the following simple code

    Code (CSharp):
    1.  
    2.         testmath = 0f;
    3.         print("testmath start = " + testmath);
    4.         testmath = testmath + 0.4f + 0.4f + 0.4f;
    5.         print("testmath add = " + testmath);
    6.         testmath = testmath - 0.4f;
    7.         print("testmath sub = " + testmath);
    8.  
    Result:
    testmath start = 0
    testmath add = 1.2
    testmath sub = 0.8000001

    This is not just a print issue, I also made:
    Code (CSharp):
    1.  
    2.         if (testmath != 0.8f)
    3.             print("Real issue");
    4.  
    And unity print the 'Real issue' string.
    So there is a real bug with float variables or I'm doing sometrhing wrong?

    Thanks!
     
    Last edited: Feb 20, 2018
  2. Rotary-Heart

    Rotary-Heart

    Joined:
    Dec 18, 2012
    Posts:
    804
    Velth likes this.
  3. Velth

    Velth

    Joined:
    Feb 20, 2018
    Posts:
    4
    Tags added.

    About the 'result is expected', are you sure about it?
    I can understand if I add and subtract different variables with different precisions, but If I add and subtract two constant why I must get two different values?

    Other than this, I temporary solved adding a first cast to decimal during the add\sub and then cast againt to float but this doesn't seem a valid solution to me.

    Code (CSharp):
    1.  
    2.         testmath = 0f;
    3.         print("testmath start = " + testmath);
    4.         testmath = (float) ((decimal) testmath + 0.2m + 0.2m + 0.2m);
    5.         print("testmath add = " + testmath);
    6.         testmath = (float)((decimal) testmath - 0.2m - 0.2m - 0.2m);
    7.         print("testmath sub = " + testmath);
    8.  
    Result:
    testmath start = 0
    testmath add = 0.6
    testmath sub = 0
     
  4. Rotary-Heart

    Rotary-Heart

    Joined:
    Dec 18, 2012
    Posts:
    804
    Yes I am sure about it, that's just the way computer works. You could even get the same result if you copy and paste (duplicate) a object on your hierarchy. You will see that the scale or the rotation will not be the same. Instead of being 1 is 0.99999999 or anything else. I recommend you to do a research on computers and floating calculations.

    As for your temporary solution. That might work now, but don't be surprised if stops working.

    What are you trying to accomplish?
     
    SparrowGS likes this.
  5. Velth

    Velth

    Joined:
    Feb 20, 2018
    Posts:
    4
    "I recommend you to do a research on computers and floating calculations."
    Thanks for the recommendation, I reccomend you to do a research on how not to be rude when you are helping someone.

    I'm working on zoom camera, I start added and subtract a constat when user use the mouse wheel.
    Checking the variable on Inspector I saw that after the third zoom out my variable was not I expected.
     
    Last edited: Feb 20, 2018
  6. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    They weren't being rude, from your question and what you've said here you are missing the basics on how computers and particularly how binary works with floating point numbers. The forums aren't somewhere where we are going to teach you basic computer science, that is something you can do in your own time so the help you are receiving here makes more sense.
     
    XCPU, SparrowGS and Rotary-Heart like this.
  7. Fido789

    Fido789

    Joined:
    Feb 26, 2013
    Posts:
    343
    Don't bite the hand that feeds you.
     
  8. Velth

    Velth

    Joined:
    Feb 20, 2018
    Posts:
    4
    ok, so thanks for your time, I'll go studing floating point math.

    That was not my intention, but usually when I speak with someone that knows less than me, and ask help, I try to be more soft.
    Anyway probably was just me that read in a wrong way the Rotary-Heart reply.
     
  9. Rotary-Heart

    Rotary-Heart

    Joined:
    Dec 18, 2012
    Posts:
    804
    I know that trying to solve a bug can be frustrating and I apologize if you found what I wrote rude, but I meant it on an educational way. There is literally nothing we can do, that's how the computer handle binary with floating point numbers.

    As for what you are doing, if you need to compare it use my suggestion.
     
    Velth likes this.
  10. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,077
    A useful thing to remember is that floating point is stored as a combination of binary fractions (1/2,1/4,1/8,1/16) so these are the only values that can be stored 'exactly'. For example, you can store 0.125 correctly because it's 1/8 but not 0.2.The code you posted would actually work ok with 0.25 but it's generally better practice not to compare floating point without some kind of approximation.

    The accuracy is also dependent on the range so you can store values like 0.12345 and 1234500000000 but you can't store 1234500000000.12345 unless you're using more than 24-bit precision.
     
    SparrowGS and Velth like this.
  11. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/float

    Observe where it says "Precision: 7 digits"

    If, over time, you start forgetting stuff about floats and how they work, at least make sure that's one thing you remember: "7 digits".

    That means if you have a floating point value of "1234567", you won't be able to add 0.001 to it with any meaningful results.

    Likewise, if you have a floating point value of "0.000001", you won't be able to add 123 to it in a meaningful way.

    Bottom line: If you need accuracy, don't use floats.