apldyalog

Dyalog Trying to understand a Floating Point rounding issue


I'm trying to understand an FP issue that I presume is rounding but not sure. I have the script below that I have typed in from a Decimal Computation Schmid 1974.

LOG X;I;J
 OUT←0,0,0,(PX←X),S←J←1-I←1
 A←8⍴0
L1:A[I]←1+(SI←¯1*I)×10*2-I
 A[1]←0.1
L2:PX←A[I]×P←PX
 S←S-⍟(A[I])
 OUT←OUT,(J←J+1),(I-2),A[I],PX,S
 →((×PX-1)=×P-1)/L2
 →(9>I←I+1)/L1
 'STEP I.    A[I].   P-REGISTER. S-REGISTER'
 4 0 2 0 11 8 13 8 13 8⍕(27 5)⍴OUT
 ' '
 'TABLE 6-2:GENERATING LOG X WITH THE SEQUENTIAL TABLE LOOKUP TECHNIQUE'
 'THIS EXAMPLE ILLUSTRATES THAT LOG(2.1) CAN BE GENERATED'
 'IN 27 STEPS WITH AN ERROR OF ONLY',(⍟X)-S
 'S=',S
 'MACHINE LOG X=',(⍟X)

I believe this to be a faithful copy of the APL (though I have only a physical copy of the book.) The only change I have made to get this to run is to use ⍕ whereas the original used DFT which I believe is an APL/360 format command. Plus I added the final two lines as extra debugging line (see below.)

In the book when this is run as LOG 2.1 the error is printed as

IN 27 STEPS WITH AN ERROR OF ONLY 5.400573684E¯7

If I run under Dyalog I get

      ⎕PP←16
      ⎕FR←645
      LOG 2.1
STEP I.    A[I].   P-REGISTER. S-REGISTER
   0 0 0.0000000000000000  2.100000000000000_  0.0000000000000000
   1¯1 0.1000000000000000  0.2100000000000000  2.302585092994046_
   2 0 2.000000000000000_  0.4200000000000000  1.609437912434100_
   3 0 2.000000000000000_  0.8400000000000001  0.9162907318741548
   4 0 2.000000000000000_  1.680000000000000_  0.2231435513142095
   5 1 0.9000000000000000  1.512000000000000_  0.3285040669720358
   6 1 0.9000000000000000  1.360800000000000_  0.4338645826298621
   7 1 0.9000000000000000  1.224720000000000_  0.5392250982876883
   8 1 0.9000000000000000  1.102248000000000_  0.6445856139455146
   9 1 0.9000000000000000  0.9920232000000003  0.7499461296033410
  10 2 1.010000000000000_  1.001943432000000_  0.7399957987501729
  11 3 0.9990000000000000  1.000941488568000_  0.7409962990837564
  12 3 0.9990000000000000  0.9999405470794321  0.7419967994173400
  13 4 1.000100000000000_  1.000040541134140_  0.7418968044170067
  14 5 0.9999900000000000  1.000030540728729_  0.7419068044670070
  15 5 0.9999900000000000  1.000020540423321_  0.7419168045170073
  16 5 0.9999900000000000  1.000010540217917_  0.7419268045670075
  17 5 0.9999900000000000  1.000000540112515_  0.7419368046170078
  18 5 0.9999900000000000  0.9999905401071139  0.7419468046670081
  19 6 1.000001000000000_  0.9999915400976539  0.7419458046675083
  20 6 1.000001000000000_  0.9999925400891939  0.7419448046680084
  21 6 1.000001000000000_  0.9999935400817339  0.7419438046685085
  22 6 1.000001000000000_  0.9999945400752739  0.7419428046690086
  23 6 1.000001000000000_  0.9999955400698138  0.7419418046695088
  24 6 1.000001000000000_  0.9999965400653539  0.7419408046700089
  25 6 1.000001000000000_  0.9999975400618939  0.7419398046705090
  26 6 1.000001000000000_  0.9999985400594339  0.7419388046710091
 
TABLE 6-2:GENERATING LOG X WITH THE SEQUENTIAL TABLE LOOKUP TECHNIQUE
THIS EXAMPLE ILLUSTRATES THAT LOG(2.1) CAN BE GENERATED
IN 27 STEPS WITH AN ERROR OF ONLY 5.400573679370524E¯7
S= 0.7419368046720094
MACHINE LOG X= 0.7419373447293773


      ⎕FR←1287
      LOG 2.1
STEP I.    A[I].   P-REGISTER. S-REGISTER
   0 0 0.0000000000000000  2.1000000000000000  0.0000000000000000
   1¯1 0.1000000000000000  0.2100000000000000  2.3025850929940457
   2 0 2.0000000000000000  0.4200000000000000  1.6094379124341004
   3 0 2.0000000000000000  0.8400000000000000  0.9162907318741551
   4 0 2.0000000000000000  1.6800000000000000  0.2231435513142098
   5 1 0.9000000000000000  1.5120000000000000  0.3285040669720361
   6 1 0.9000000000000000  1.3608000000000000  0.4338645826298624
   7 1 0.9000000000000000  1.2247200000000000  0.5392250982876887
   8 1 0.9000000000000000  1.1022480000000000  0.6445856139455150
   9 1 0.9000000000000000  0.9920232000000000  0.7499461296033413
  10 2 1.0100000000000000  1.0019434320000000  0.7399957987501732
  11 3 0.9990000000000000  1.0009414885680000  0.7409962990837567
  12 3 0.9990000000000000  0.9999405470794320  0.7419967994173402
  13 4 1.0001000000000000  1.0000405411341399  0.7418968044170069
  14 5 0.9999900000000000  1.0000305407287286  0.7419068044670073
  15 5 0.9999900000000000  1.0000205404233213  0.7419168045170076
  16 5 0.9999900000000000  1.0000105402179171  0.7419268045670079
  17 5 0.9999900000000000  1.0000005401125149  0.7419368046170083
  18 5 0.9999900000000000  0.9999905401071138  0.7419468046670086
  19 6 1.0000010000000000  0.9999915400976539  0.7419458046675086
  20 6 1.0000010000000000  0.9999925400891940  0.7419448046680086
  21 6 1.0000010000000000  0.9999935400817341  0.7419438046685086
  22 6 1.0000010000000000  0.9999945400752742  0.7419428046690086
  23 6 1.0000010000000000  0.9999955400698142  0.7419418046695086
  24 6 1.0000010000000000  0.9999965400653543  0.7419408046700086
  25 6 1.0000010000000000  0.9999975400618944  0.7419398046705086
  26 6 1.0000010000000000  0.9999985400594344  0.7419388046710086
 
TABLE 6-2:GENERATING LOG X WITH THE SEQUENTIAL TABLE LOOKUP TECHNIQUE
THIS EXAMPLE ILLUSTRATES THAT LOG(2.1) CAN BE GENERATED
IN 27 STEPS WITH AN ERROR OF ONLY 5.400573687114162E¯7
S= 0.7419368046720086
MACHINE LOG X= 0.7419373447293773

As I understand it ⎕FR←1287 sets up a high-precision FP representation that uses 128-bits.

So the three different runs, differ at:

8.4E^-15 Unknown presumed APL/360
7.9E^-15 Dyalog 19.0 Apple M1 Normal precision
8.7E^-15 Dyalog 19.0 Apple M1 High precision

I'm trying to understand the difference. The log value is the same across at least the two Dyalog versions.The difference is in the S value which between the two Dyalog versions starts to deviate at STEP 11.


Solution

  • So I did find the answer. Shortly after pressing the post for the question. The docs on FORMAT:

    https://help.dyalog.com/19.0/index.htm#Language/System%20Functions/Format%20Dyadic.htm?Highlight=_

    Mention that the underscore is the

    _ loss of precision character
    

    "If the number of specified significant digits exceeds the internal precision"

    There are several _ in the print out for PX and S in the normal precision prior to actual values differing so obviously this where the rounding error is occurring.

       4 0 2.000000000000000_  1.680000000000000_  0.2231435513142095
       5 1 0.9000000000000000  1.512000000000000_  0.3285040669720358
       6 1 0.9000000000000000  1.360800000000000_  0.4338645826298621
       7 1 0.9000000000000000  1.224720000000000_  0.5392250982876883
       8 1 0.9000000000000000  1.102248000000000_  0.6445856139455146
       9 1 0.9000000000000000  0.9920232000000003  0.7499461296033410
      10 2 1.010000000000000_  1.001943432000000_  0.7399957987501729
      11 3 0.9990000000000000  1.000941488568000_  0.7409962990837564
      12 3 0.9990000000000000  0.9999405470794321  0.7419967994173400
    

    On reflection the fact that Dyalog/APL format gives this information is incredibly cool and very useful!