     POV-Ray : Newsgroups : povray.newusers : mod() and floating point division woes. :( : Re: mod() and floating point division woes. :( Server Time17 Aug 2022 09:42:41 EDT (-0400) Re: mod() and floating point division woes. :(   From: clipka Date: 3 Sep 2018 20:13:19 Message: <5b8dce1f\$1@news.povray.org>    ```
{
"@context": "https://schema.org",
"@type": "DiscussionForumPosting",
"@id": "#5b8dce1f%241%40news.povray.org",
"headline": "Re: mod() and floating point division woes. :(",
"dateCreated": "2018-09-04T00:13:19+00:00",
"datePublished": "2018-09-04T00:13:19+00:00",
"author": {
"@type": "Person",
"name": "clipka"
}
}
Am 03.09.2018 um 14:32 schrieb Bald Eagle:

> At some point 1/5 ought to "equal 0.2" in an absolute, Boolean, true/false way,
> and not some - well it's actually kinda sorta 0.2 +/- E way.

The problem is rarely with just a single mathematical operation - a
proper implementation of the C/C++ floating-point library functions will
alway compute the exact result, rounded by some standardized mechanism.
(That rounding mode is more or less arbitrary, but is consistent. So for
instance an implementation may round all results towards zero. Or it may
round all results towards negative infinity.)

So while it is not guaranteed that 1/5 can be represented exactly, nor
whether the result will be a bit too high or too low, it is guaranteed
to use the same representation as converting the string "0.2" to
floating point, or computing 3/15. In other words, the results are
ROUND(1/5), ROUND(0.2) and ROUND(3/15), respectively, where ROUND() is
the implementation's rounding scheme. So since A=B => ROUND(A)=ROUND(B),
such results compare perfectly equal.

The problem arises when the inexactly-represented interim results of one
operation are used as parameter to another operation, and /then/ the end
result compared to a value obtained differently. For example, it is
/not/ guaranteed that the result of (1/5)+(2/5) will equal 3/5, because
the former will be approximated as ROUND(ROUND(1/5)+ROUND(2/5)) =
ROUND((1/5+ERROR1)+(2/5+ERROR2)) = ROUND(1/5+ERROR1+ERROR2), while the
latter will just be ROUND(1/5).

Worst offenders are additions of numbers with significantly different
magnitudes, by the way.

> Then there's --- the POV-Ray source code itself, where I found this:
> https://github.com/POV-Ray/povray/blob/master/source/base/mathutil.h

Some fun facts in there, eh?
Learned those nasty details the hard way.

Sometimes I think we should really be doing math on ranges rather than
single floating point numbers; that way we can really tell how precise
any given computed value is, and testing whether two results are equal
would really mean testing if the computed ranges have at least one value
in common.
```    