Download

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


float float1;
float1 = 0.000000000000000001;
float newfloat;
newfloat = float1 + 0.000000000000000001;

the result is still
newfloat = 0.000000000000000001

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

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

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.

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

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.



 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.

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.


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


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

???

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.

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.

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.

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.