roh@gmdzi.UUCP (Peter Rohleder ) (02/28/89)
It seems that we have found a severe bug in the Apples SANE-Package. We found it when we tried to figure out whether an EXTENDED has digits unequal zero behind a predefined position after the decimalpoint. The only(?) way to figure this out seems to shift this significant position before the decimalpoint by multiplication, then to truncate the value(we used Rint cause trunc also didn't work) and then making the opposite operation and comparing the value against the original value. If it is not equal you can say that obviously the value has digits nonzero after the fourth position behind the decimalpoint. Otherwise you can say that there are no digits unequal zero behind a predefined position. We wrote following short test program including some features to make the bug obvious. It should be easy to execute it in the MPW-Pascal or LightSpeedPascal Environment. The program reads out of a testfile. Try to use values like 0.004 or 0.09 or 0.01 or 0.3. The Relation-operation in this cases should always return with EqualTo but it doesn't. Is this really a severe bug in the SANE-Package or is there anything wrong in our understanding of the precision of the different operations in SANE. Also any other ideas to figure out whether a value has significat digits after a predefined position behind the decimalpoint are helpful and welcome! PROGRAM Teststr; USES {$LOAD MacIntf.LOAD} {Memtypes, QuickDraw, OSIntf, ToolIntf, PackIntf, FixMath,} SANE; CONST z = 10000; kDelta = 1E-18; VAR s : DecStr; f : DecForm; i : INTEGER; va : Extended; re : RelOp; t : Text; a, b, c : Extended; FUNCTION CompExtended(a,b: EXTENDED): RelOp; VAR d: Extended; BEGIN IF (a=0.0) OR (b=0.0) THEN CompExtended := Relation(a,b) ELSE BEGIN d := ABS(a - b); IF Relation(d,kDelta)= LessThan THEN CompExtended := EqualTo ELSE CompExtended := Relation(a,b); END; END; PROCEDURE PrintBitstring (a : Extended); VAR t : RECORD CASE INTEGER OF 1 : ( x : Extended ); 2 : ( b : PACKED ARRAY[0..79] OF BOOLEAN ); 3 : ( f : ARRAY[0..4] OF INTEGER ); END; i : INTEGER; BEGIN t.x := a; Write(a : 50 : 30,' / ',a, ': '); FOR i := 0 TO 79 DO BEGIN IF t.b[i] = TRUE THEN Write('1') ELSE Write('0'); IF i = 16 THEN Write(' '); END; FOR i := 0 TO 4 DO BEGIN Write(t.f[i]) END; Write(' Numclass:', ORD(ClassExtended(a))); WriteLn; END; BEGIN Reset(t, 'TestFile'); WHILE NOT EOF(t) DO BEGIN ReadLn(t, va); PrintBitString(va); a := va * z; b := Rint(a); c := a - b; WriteLn(a); WriteLn(b); WriteLn(c); Re := CompExtended(a, b); CASE Re OF GreaterThan : WriteLn('Greaterthan'); LessThan : WriteLN('LessThan'); EqualTo : WritelN('EqualTo'); Unordered : WriteLn('uordered'); END; END; Close(t); END. Thanks in advance! Peter Rohleder e-mail address: roh@gmdzi.uucp
lippin@wheatena.berkeley.edu (The Apathist) (03/02/89)
Recently roh@gmdzi.UUCP (Peter Rohleder ) wrote: > >It seems that we have found a severe bug in the Apples SANE-Package. > >We found it when we tried to figure out whether an EXTENDED has >digits unequal zero behind a predefined position after the decimalpoint. [...] >Is this really a severe bug in the SANE-Package or is there anything wrong >in our understanding of the precision of the different operations in SANE. I don't think this is really a bug; the problem lies in the necessary inaccuracy of applying the decimal concept of digits to the binary representations of SANE. In your relation test, you are (correctly) using a fudge factor in the check for equality, to avoid errors in the last few bits. However, you neglect to scale the fudge factor along with the numbers you are comparing, and so when you multiply by 10000, the errors in representation become greater than your saftey margin. I suspect, though I haven't tried it, that if you raise kDelta to 1E-14 your example program will work. --Tom Lippincott lippin@math.berkeley.edu "Thank you for observing all saftey precautions." --Dark Star