On 12/11/2024 22:44, James K. Lowden wrote:
On Tue, 12 Nov 2024 18:12:50 +0100
David Brown via Gcc <gcc@gcc.gnu.org> wrote:
Under what circumstances would you have code that :
...
d) Would be perfectly happy with "x" having the value 2.225e-307 (or
perhaps a little larger) and doing the division with that.
I think what you really want to check is if "x" is a reasonable value
- checking only for exactly 0.0 is usually a lazy and useless attempt
at such checks.
In quantitative research, "x" may be initialized from a database.
Yesterday that database might have been fine, and today there's a row
with a zero in it. If it's a problem, it's better to report the
problem as "x is 0 for foo" than as a divide-by-zero error later on.
No. This is - or at least appears to be - missing critical thinking.
If you have data from a database, and you are not completely sure that
you have full control over the data and know that it is always valid
(for whatever operations you will do with the data), then it is
"external data". That means you need to do a full check for sane, safe
and valid data before you use it - just as you would for data from a
user-provided file, an internet web form, or anything else untrusted.
And it is simply not credible that the only check for validity of "x" is
to check for a value of exactly 0.0. (What about a null entry? A NaN ?
A value that is simply too big or too small?)
In fact, division might not be the issue. A coefficient of zero might
indicate, say, an error upstream in the model parameter output.
That would be a design flaw - 0.0 is not (in general) a good way to
indicate such things. Use a NaN if you need to keep it within a float -
or, better, use a database Null entry or an additional validity or error
signal.
In the kind of situation where 0.0 could be a practical choice for
indicating an error or missing data, you have a clear gap between
invalid data and valid data - and you use "x > 0.0" for the check, not
"x == 0.0" (after first checking for NaNs and other awkward values if
you got it straight from the database).
It's also not unusual to start with "x" statically initialized to zero,
and use that as an indication to invoke the initialization routine.
Use 0.0 as the starting point if that makes sense - it often does.
Don't use it as a flag for invoking other things. (Or, if you have
enough control of the data to be sure it is safe to do so, at least use
greater than comparisons rather than equality.)
When we have floating point numbers initialized from small integer
constants, comparison with == is both valid and safe. Whether 0 itself
is the concern, or near-zeroes like 2.225e-307, is depends on context,
something the programmer knows and the compiler does not.
Certainly it is the programmer that knows what is valid or not, and how
it is appropriate to test for validity. And the programmer should know
that testing for floating point /equality/, even comparing to 0.0, is a
questionable choice of strategy. That's why this is a useful warning in
the compiler. And if you have a point in your code where you are
absolutely sure it is safe and useful to compare floats for equality,
then turn off the warning around that bit of code, along with a comment
to say how you know it is safe, why you think it is a good idea here,
and what future maintainers should watch out for if they change the
code. That way, future readers of the code (perhaps yourself, after
many years) will not have to wonder why the programmer is using risky
code techniques.