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. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

Crazy Floating Point Inaccuracy Contradicting Itself

Discussion in 'Scripting' started by AnimalMan, Sep 25, 2022.

  1. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,015
    Now i am aware the bug is specific to my particular project so i am not sure you'll be able to replicate it, and right now i wouldn't be able to provide all of the code for the project so you could see it, and even so i don't think a solution can be provided. However i got a weird instance of floating point inaccuracy, maybe you guys have a tip or suggestion or something to say about it.

    First up I am comparing Vector Right and Vector Forward of an object to decide a limited number of object facings that I want, its relevant down the line to art style uv and lighting efficiency.

    Here i ask
    Code (CSharp):
    1.  
    2.             if (RIGHT.x < 0 && RIGHT.z < 0)
    3.             {
    4.                 if (FORWARD.x > 0 && RIGHT.z < 0)
    5.                 {
    6.                     UPHILL = 1;
    7.                     Debug.Log("WHY THIS" + RIGHT.x + " " + RIGHT.z + " " + RIGHT);
    8.                 }
    9.             }
    The result returned is contradictive == WHY THIS -1.117587E-07 -1 (0.00, 0.00, -1.00)

    Its telling me 0.00 = -1.117587E-07 on the X; So a request for Right gives me 0, 0, -1, but a specific request for Right.x gives me -1.117587E-07.

    I don't know how to write -1.117587E-07 in code and have it be read and recognized that this result is same as zero and as you can see the full debug of vector RIGHT returns 0.00, 0.00 -1.00

    We are correct on the Z of -1, but that X is just a straight up floating point failure.

    Well what's happening? I suspect voltage is leaking into it. And its registering a microscopic value, and this would be something going on in the microchip. I am not able to ask for the int in this case simply because sometimes my right is at a 45 degree angle or diagonal or pitch and yaw, and so both return a value that is needed for example a right of 0.21, 0, -0.21 may be needed. In which case the int would cause further bugs or inability to check those values and run logic.

    I'm not angry or anything, I have become much more enlightened and calm as I improve, and I think I can figure this out if I think about it. But I am aware there are a bunch of smart people on the forum so I just thought I'd flag occurrence of it in the public and see what if anything you would do without stringing this number to string. Or do you suspect this is a rare instance where string is the only way to read this number.

    Anyways

    Hope I wrote clearly it enough. Let me know what you think.
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,231
    This is just an issue of the default string formatting for Vector3 only showing 1-2 decimal points. This is not some freak microchip failiure. Try this:
    Code (CSharp):
    1. Debug.Log("Better formatting: " + RIGHT.x.ToString("F12") + " " + RIGHT.z.ToString("F12") + " " + RIGHT.ToString("F12"));
     
  3. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,015
    The code shouldn't even be entered as RIGHT.x = 0.

    So I have to make a string and compare strings instead of Vector floats?

    Code (CSharp):
    1.  
    2.             if (RIGHT.x < 0 && RIGHT.z < 0)
    3.             {
    4.                 if (FORWARD.x > 0 && RIGHT.z < 0)
    5.                 {
    6.                     UPHILL = 1;
    7.                     Debug.Log("WHY THIS" + RIGHT.x + " " + RIGHT.z + " " + RIGHT);
    8.                 }
    9.             }
    BUG.png
     
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,231
    No you don't need to do string comparisons. You said it yourself RIGHT.x is NOT 0, it is -1.117587E-07, which is a very small negative number.
     
  5. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,015
    A trick if I grab the very small negative number and check if right.x + very small negative number is still less than 0 then we can run the logic.

    hmm

    I need to log and keep in memory the very small negative number and call it FloatingPointBug and then check 0 + floatingpointbug to see if its still less than zero :S

    Public static constant FloatingPointBug :D
     
  6. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,015
    Yah i can write

    Code (CSharp):
    1. static float FLOATINGBUG = -1.117587E-07f;

    Code (CSharp):
    1.  
    2.            else if (RIGHT.x - FLOATINGBUG < 0 && RIGHT.z < 0)
    3.             {
    4.                 if (FORWARD.x > 0 && RIGHT.z < 0)
    5.                 {
    6.                     UPHILL = 1;
    7.                     Debug.Log("WHY THIS" + RIGHT.x + " " + RIGHT.z + " " + RIGHT);
    8.                 }
    9.             }
     
  7. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    It's not a bug. -1.117587E-07f is zero with floating point precision. You might consider https://docs.unity3d.com/ScriptReference/Mathf.Approximately.html
     
    AnimalMan likes this.
  8. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,015
    That'll be the ticket

    For the record you can't subtract this though I did test it.

    Mathf.Approx will work fine I am sure of it


    Thank you
     
    JeffDUnity3D likes this.
  9. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,015
    It didnt actually work. However i am abit of a dummy

    So now i am

    Code (CSharp):
    1. using System;
    Code (CSharp):
    1. Math.Round(RIGHT.x, 2)
    or better yet

    Code (CSharp):
    1. RIGHT = new Vector3((float)Math.Round(RIGHT.x, 2), (float)Math.Round(RIGHT.y, 2), (float)Math.Round(RIGHT.z, 2));
     
  10. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,231
    This whole thread is a little bit of an XY problem to be honest. If you want the best answer for how to accomplish your goals, you should explain what exactly you're trying to accomplish here.

    https://xyproblem.info/
     
  11. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,722
    What the heck is that? Looks like no code I've seen ever to compare floats. I think like others have said - please state your actual use case rather than trying to make your non-working solution, work as likely there are a lot of solutions in this space.
     
  12. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,015
    Good Question, by the way I am sorry about winding you up before. I didn't mean to seem so crazy.

    But Good Question!!!!

    GOOD QUESTION INDEED
    :p

    Now the unit is moving very slow while i check the angles, He does move much faster.

     
    hippocoder likes this.
  13. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,015
    So the Unity Vector3 position is a Double not a float :) so we Float the double and then round the float of the double.

    I think I got it under control.
     
  14. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,722
    The Unity Vector3 position is a float, but Debug Log or print will truncate the number when printing it out, unless you print out the individual x, y or z elements. Is this what you were referring to? System.Math probably uses doubles though.
     
    AnimalMan likes this.
  15. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,015
    My mistake the return is the double but it’s rounded to the specified decimal and converted to float for unity

    the odd part was, and the reason for the thread is that 90% of the code functioned correctly and was able to successfully detect a negative or positive, only a small minority of directions started to require rounding. So I had actually written 95% of the required code before I found that the floating point inaccuracy was present. It will be useful for the future in comparing vectors. The other method posted returned a bool true or false and so couldn’t be used on a > greater than or less than < check.
     
    Last edited: Sep 25, 2022
    hippocoder likes this.
unityunity