Announcement

Collapse
No announcement yet.

Issues with float mathematics (Can't add 0.000000000000000001 + storedfloat);

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Issues with float mathematics (Can't add 0.000000000000000001 + storedfloat);

    I'm trying to add a float to a stored float
    0.000000000000000001 + 0.000000000000000001 does = 0.000000000000000002
    and even adding to weird numbers such as 0.000000000000011111 will work

    But if I store 0.000000000000000001 in a float and add 0.000000000000000001 to that float
    it will not = 0.000000000000000002, instead still 0.000000000000000001

    Code:
    float float1;
    float1 = 0.000000000000000001;
    float newfloat;
    newfloat = float1 + 0.000000000000000001;
    the result is still
    newfloat = 0.000000000000000001


  • #2
    That is because floating points only have limited precision. You should never expect infinite precision when dealing with floats.
    This is also the reason why you will find NearlyEqualTo functions in the UE4 (and other) math library.
    For more on the subject search for "floating point arithmetic".

    In any case, you could use a double if you want just a bit more precision (it uses more precision bits) - but it still has the same limitations
    Last edited by Semitable; 09-21-2017, 04:27 PM.
    Check my User Interface Kit here: https://forums.unrealengine.com/show...-Interface-Kit
    A WIP Hex Planet Generation: https://forums.unrealengine.com/show...ral-Generation

    Comment


    • #3
      I cant see any valid reason to use such precision in a game, unless you are doing something really crazy , why not?,
      you should use double, but if you want something much crazy and loose your mind then use long double

      Comment


      • #4
        Also, I forgot to mention why you are getting the correct value when doing it like this: 0.00001 + 0.00001.
        By default those values are doubles . If you want to get a float you must write it like this: 0.1f (postfix an F)

        So what is happening is that the COMPILER adds those values as doubles (hence more precision) and then assigns the value to your float.
        While in the latter example you convert float1 to a float BEFORE adding it to the other 0.0001. That;s the difference.

        Also afaik in the win64 visual studio compiler that I have, double and long double are the same (sizeof(double) == (sizeof(long double) == 8, try it). Don't know if you will get a different result in another compiler, but the point is that you should not rely on this. You should really learn to work with imprecision when using floats, else your code won't always work.
        Check my User Interface Kit here: https://forums.unrealengine.com/show...-Interface-Kit
        A WIP Hex Planet Generation: https://forums.unrealengine.com/show...ral-Generation

        Comment


        • #5
          Even with converting both to floats I result the same error.

          Comment


          • #6
            This is not an error. This is how floats and doubles work. Doubles just offer higher precision but this will ALWAYS happen.

            I don't understand why you converted them both to float and what you were expecting. You could have converted them to double: e.g.
            Code:
             double mydouble;
            mydouble = 0.000000000000000001;
            double newdouble;
            newdouble = mydouble + 0.000000000000000001;
            this might work but it might not work. You can never know.
            All you know is that FMath::IsNearlyEqual(A, B) will return true if A is = float1 + float2 and B is 0.000000002.
            Check my User Interface Kit here: https://forums.unrealengine.com/show...-Interface-Kit
            A WIP Hex Planet Generation: https://forums.unrealengine.com/show...ral-Generation

            Comment


            • #7
              The float I'm trying to add is from a callback, any time I add anything to it besides itself it just results in the default number.

              Comment


              • #8
                Code:
                void MyWidget::MyCallBack(float MyFloat)
                {
                
                    //doubletest2 = FMath::Abs(scrollValue);
                    float floattest;
                    floattest = 0.000000000000000001f;
                    float floattest2;
                    floattest2 = MyFloat + floattest;
                
                    FString Test66 = GetFloatAsStringWithPrecision(floattest2, 18);
                    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, Test66);
                }
                "floattest2" results the same as "MyFloat" in the above

                Code:
                void MyWidget::MyCallBack(float MyFloat)
                {
                    floattest2 = MyFloat + MyFloat;
                
                    FString Test66 = GetFloatAsStringWithPrecision(floattest2, 18);
                    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, Test66);
                }
                "floattest2" has been successfully doubled in the above

                ?????????????



                Comment


                • #9
                  That's because in example 2, you are adding two floats together who are in relatively the same range (very small numbers). The problem occurs when you have floats of widely different values being used together. It's called floating-point error and is a well known caveat of any and all floating-point operations. Sometimes, things work by fluke - other times they won't.

                  https://en.wikipedia.org/wiki/Single...g-point_format

                  Most FMath functions work only with floats, and will therefore convert/cast your double to a float when you use them - so often you have to call the platform-specific implementation directly. If you do all of your floating-point operations in doubles and cast back to floats at the VERY end, you might be able to use them.

                  Comment


                  • #10
                    I would say if you need that much precision you are likely doing something wrong. Only complex science simulations use values that precise and generally they use a fixed point math to get around the limits / add stability. In 99.9% of the normal cases of floating point math - you only need 4 - 6 decimal places worth of precision.
                    Able Ability System - A high performance, robust ability system for UE4. Now Available!

                    Comment


                    • #11
                      You are expecting way too much precision for floats with values so small. Take a look at the constants epic defines for use in their math functions to get a ballpark idea of the ranges of precision you should be working within. Precision up to 1e-8 is probably as precise as you should attempt to keep rounding error relatively in check. Even that will not always be acceptable under many circumstances. Depending on what you are doing, you could probably even use 1e-4 precision and still have more than enough accuracy for your requirements.

                      Comment

                      Working...
                      X