POV-Ray : Newsgroups : povray.general : Re: (X <= D) is not equal ((X<D) | (X=D)) : Re: (X <= D) is not equal ((X<D) | (X=D)) Server Time
9 Aug 2024 23:29:43 EDT (-0400)
  Re: (X <= D) is not equal ((X<D) | (X=D))  
From: Peter J  Holzer
Date: 24 Apr 2000 16:01:20
Message: <slrn8g6h9p.e85.hjp-usenet@teal.h.hjp.at>
On Sat, 22 Apr 2000 14:43:54 -0500, Thorsten Froehlich wrote:
>
>CAUSE AND FIX OF THE PROBLEM:
>
>Technically it is not a bug but a limit in floating-point precision
>which is not properly documented. The reason why the first one works
>is rather simple: POV-Ray already contains a workaround for "is equal"
>comparisons as well as "is not equal" ones, but not for smaller/greater
>(or equal) than ones. In reality POV-Ray fixes the problem for the
>equal and not equal cases with this method:
>
>condition:   f1 = f2
>POV-Ray:     if (fabs(f1 - f2) > EPSILON) then false else true
>
>condition:   f1 != f2
>POV-Ray:     if (fabs(f1 - f2) > EPSILON) then true else false
>
>The other comparison operators do not take EPSILON into account.  So
>practically POV-Ray should contain a workaround for these cases as well.

I disagree. This workaround assumes that all numbers are in a certain
range (about 1E-3 ... 1E6). While this may be true for most scenes it
certainly isn't universally true. In my scene files one pov unit is
always one meter, whether I am modelling the circuits of a microchip or
the whole solar system. 
 From reading IRTC entry descriptions I get the impression that I am not
the only one who puts the sun at the correct distance even for "everyday
scenes". I have occasionally encountered weird behaviour at large
scales, which I now suspect to be caused by this workaround (I will
check this and then post a followup).

A better expression for a "fuzzy" equality operator would be:

f1 == f2 ? 1 : fabs(f1 - f2) / max(fabs(f1), fabs(f2)) < EPSILON

but I don't think it should be fuzzy at all.

>Further, the documentation should make clear that floating-point math is
>_not_ precise.

Right. Especially make it clear that floating point numbers are binary
and cannot exactly represent fractions which are not a multiple of some
power of two. 1/2, 3/4, 356/1024 can be exactly represented, but 1/10
cannot (just like 1/3 cannot be exactly represented in decimal).
Therefore 10 * 0.1 is not equal to 1. 

Instead of 

#local D = 2;
#local X = -D;
#while (X <= D)
   #local X = X + 0.1;
   do_something_with(X)
#end

write 

#local D = 20;
#local X1 = -D;
#while (X1 <= D)
   #local X1 = X1 + 1;
   #local X = X/10
   do_something_with(X)
#end

this is exact and will produce the expected result.

	hp

PS: I see that EPSILON is used quite often in the sources. I have not
checked if it is used correctly in other places.

-- 
   _  | Peter J. Holzer    | Nicht an Tueren mangelt es,
|_|_) | Sysadmin WSR       | sondern an der Einrichtung (aka Content).
| |   | hjp### [at] wsracat      |    -- Ale### [at] univieacat
__/   | http://www.hjp.at/ |       zum Thema Portale in at.linux


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.