1

There are a lot of articles, PhD publications, books and question here on this topic, still my question will be pretty straightforward.

How can we improve this or workaround without writing dozens of ifs?

Suppose I have 2 doubles;

double d1 = ..;
double d2 = ..;

The most naïve think we can try to do is to try if(d1==d2) // baaaad!!!, as we know we can fail on precision mismatches on very close values.

Second naïve thing can be if(std::abs(d1-d2) < std::numeric_limits<double>::epsilon())
This still fails for relatively big doubles as std::numeric_limits<double>::epsilon() described as follows:

Returns the machine epsilon, that is, the difference between 1.0 and the next value representable by the floating-point type T

Which for double is 0.00000000000000022204

So I came up with this:

double epsilon = std::max(d1,d2)/1E14; // I am ok with precision mismatch after 14th digit, regardless how big the number is.

The problem here is that for small numbers this fails, for instance this prints 0.00..00

double d = 1E-7;  
std::cout<<std::fixed<<std::setprecision(20)<< d/1E14;

So the question will be is there a generic solution/workaround for this, or I should write dozens of ifs to decide my denomination properly in order not to overkill the precicion?

Eduard Rostomyan
  • 7,050
  • 2
  • 37
  • 76
  • 9
    There is no single, universal, solution that produces ideal results in every possible situation. The epsilon, for each particular comparison, must be carefully chosen based on the individual and specific circumstances of the calculation that produces it. – Sam Varshavchik Apr 28 '22 at 01:12
  • If someone knew about a domain-independent way to generically handle these issues in a way that satisfied everyone, we'd be using it already. It's hard to say if "dozens of ifs" will or won't be required in your case, but you will have to think about what magnitudes you're working with and what precision you need for the computations you're doing; there's no one-size-fits-all solution. – Nathan Pierson Apr 28 '22 at 01:14
  • Knuth says: https://stackoverflow.com/a/253874/4641116 – Eljay Apr 28 '22 at 01:26

1 Answers1

1

So the question will be is there a generic solution/workaround for this

There will not be a universal solution for finite precision floating point that would apply to all use cases. There cannot be, because the correct threshold is specific to each calculation, and cannot generally be known automatically.

You have to know what you are comparing and what you are expecting from the comparison. Full explanation won't fit in this answer, but you can find most information from this blog: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ (not mine).


There is however a generic solution/workaround that side-steps the issue: Use infinite precision arithmetic. The C++ standard library does not provide an implementation of infinite precision arithmetic.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Infinite-precision arithmetic is impossible to realize. Was symbolic computation the intended term? What is available are arbitrary-precision libraries, but they do not fundamentally change the problem, just kick the can down the road towards smaller epsilons. – njuffa Apr 28 '22 at 01:46