Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
floating-point-equality [2017/04/19 11:15] – awf | floating-point-equality [2017/11/21 12:27] – awf | ||
---|---|---|---|
Line 13: | Line 13: | ||
</ | </ | ||
- | But what are you trying to avoid here? Is it the divide by zero exception? Then avoid that: | + | But what are you trying to avoid here? Is it the divide by zero? Then avoid that... |
<code C++> | <code C++> | ||
double func(double a, double b) { | double func(double a, double b) { | ||
Line 23: | Line 23: | ||
} | } | ||
</ | </ | ||
- | " | + | " |
+ | Floating point can deal with it. If you didn't need that dynamic range, you'ld be using '' | ||
+ | |||
+ | OK, what about 1e-309? | ||
+ | Now you won't get a divide by zero, most likely you'll return Inf, and... your code might run very slowly. | ||
+ | Aha! No-one wants slow code, right? | ||
+ | That's slowing down every call to the function. | ||
+ | If your workloads mostly don't call the function with nearly equal very small numbers, | ||
+ | then you can go a lot faster in the common case by not checking. | ||
+ | |||
+ | "Ah, but I want the additional error checking" | ||
+ | Why did the caller call the routine with nearly equal very small numbers? | ||
+ | Is that physically likely in whatever real-world problem you're trying | ||
+ | If not, one should probably protect at the call site with an assert. | ||
Or maybe it's a precondition of the function call that a not be equal to b, and it's a coding bug if not satisfied. | Or maybe it's a precondition of the function call that a not be equal to b, and it's a coding bug if not satisfied. | ||
<code C++> | <code C++> | ||
double func(double a, double b) { | double func(double a, double b) { | ||
- | | + | |
| | ||
} | } | ||
</ | </ | ||
- | Don't forget to [[assert-always|leave your asserts on in all builds]] unless the profiler tells you otherwise. | + | Don't forget to [[assert-always|leave your asserts on in all builds]] unless the profiler tells you otherwise. |
+ | But hang on, you're on a platform which will give you line number here when you get the divby0 right? | ||
+ | So the assert is superfluous | ||
==== But my case is more subtle than that ==== | ==== But my case is more subtle than that ==== | ||
Line 46: | Line 61: | ||
</ | </ | ||
- | Even here, you can think about what a better value to compare to might be. First note that sin(x)/x works fine for all normalized | + | Even here, you can think about what a better value to compare to might be. First note that sin(x)/x works fine for all floats except zero, so you can avoid a dependency on fabs and a definition of epsilon by just comparing to zero. |
But perhaps the profiler has told you that a big chunk of program time is spent in computing sin() and dividing, and furthermore you know that most times it's called with values near zero. Well then, let's do what we do with any special function that goes slow: chop up the domain and special case. | But perhaps the profiler has told you that a big chunk of program time is spent in computing sin() and dividing, and furthermore you know that most times it's called with values near zero. Well then, let's do what we do with any special function that goes slow: chop up the domain and special case. |