Announcement

Collapse
No announcement yet.

Standard for Floating-Point Arithmetic (IEEE 754) in PowerBasic

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Standard for Floating-Point Arithmetic (IEEE 754) in PowerBasic

    What standart PowerBasic uses in floating point arithmetic?

    I ask this, because, wend I do some calculation with doubles, the results are very differents from the results in C and JavaScript.

    The results in C are equal to JavaSript.

    The only manual reference to IEEE Standart is:

    FRAC function
    Purpose
    Return the fractional part of a number.

    Syntax
    h = FRAC(float_expression)

    Remarks
    FRAC returns the number after the decimal point of a floating-point number or expression. FRAC rounds the result of fit the precision of the target h, as per IEEE specifications.

    See also
    CEIL, CINT, FIX, INT, ROUND

    Example
    h# = FRAC(10.25#) ' = 0.25# (Double-precision)

    And this donot give identical values in confront to C or JavaScript. Why?

    Thanks

  • #2
    Because those languages calculate to a lesser precision than PowerBASIC. They take specific steps to limit the FPU precision to a total of 64 bits, while PowerBASIC utilizes the full 80-bit precision offered by the hardware. It may be they think their benchmarks will look better with less calculation... or it may be something else.

    Bob Zale
    PowerBASIC Inc.

    Comment


    • #3
      Example
      Code:
      h# = FRAC(10.25#) ' = 0.25# (Double-precision)
      And this donot give identical values in confront to C or JavaScript. Why?
      In this specific example here, everything should come out the same because decimal .25 is exactly .0100000 [0..] in binary.

      However, "how you check" may well be at the mercy of whatever functions you use to display the results.

      If you are really curious you can try individual inspection of the 64 bits of the double-precision variable.
      Last edited by Michael Mattias; 17 Oct 2010, 11:58 AM.
      Michael Mattias
      Tal Systems Inc.
      Racine WI USA
      mmattias@talsystems.com
      http://www.talsystems.com

      Comment


      • #4
        Thank you Bob, I'm very honored to talk with you.
        I follow you since the 80s. You are great, and your products have, for me, great quality.

        Allow me ask you. There are a way to have compatibility in calculations with
        i.e doubles?

        Comment


        • #5
          There are a way to have compatibility in calculations with
          i.e doubles?
          Compatibility with what? C and Java compilers will vary in their implementations by brand, just as Microsoft BASICs vary from PowerBASIC BASIC.

          But as per my post just completed... I would not be at all surprised if
          A) the 64 bits in the specific example are in fact identical
          B) The specific example you gave is
          - An unfortunate selection as .25 is an integral power of two
          - This is not the real code, as the real code is doing some calulations to obtain the operand for the FRAC function.

          Code not shown.

          MCM
          Michael Mattias
          Tal Systems Inc.
          Racine WI USA
          mmattias@talsystems.com
          http://www.talsystems.com

          Comment


          • #6
            Ribeiro,
            you can set the precision used by the FPU by doing something like this:
            Code:
            #COMPILE EXE
            #DIM ALL
            
            FUNCTION PBMAIN () AS LONG
            #REGISTER NONE   'the control words mustn't be register variables
            
            LOCAL OriginalFPUControlWord AS WORD
            LOCAL NewFPUControlWord AS WORD
            
            
            
            !fstcw OriginalFPUControlWord       'save the FPU Control Word
            NewFPUControlWord = (OriginalFPUControlWord AND &hFCFF)            'set for SINGLE (24 bits) precision
            'NewFPUControlWord = (OriginalFPUControlWord AND &hFCFF) OR &h0200  'set for DOUBLE (53 bits) precision
            'NewFPUControlWord = (OriginalFPUControlWord AND &hFCFF) OR &h0300  'set for EXT (64 bits) precision
            
            !fldcw NewFPUControlWord   'set the FPU to new precision.
            
            'put code here
            PRINT STR$(SQR(2),18)
            
            
            !fldcw OriginalFPUControlWord   'Restore to original condition
            
            WAITKEY$
            
            END FUNCTION
            Paul.

            Comment


            • #7
              Originally posted by Ribeiro Alvo View Post
              Thank you Bob, I'm very honored to talk with you.
              I follow you since the 80s. You are great, and your products have, for me, great quality.

              Allow me ask you. There are a way to have compatibility in calculations with
              i.e doubles?
              Hello Ribeiro,

              Take a look here and around
              "The trouble with quotes on the Internet is that you can never know if they are genuine." - Abraham Lincoln.

              Comment


              • #8
                Paul...

                ... running 'ipis verbis' your code, we have:

                sqr(2)=1.41421350228066304

                With Windows calculator we have:

                2^.5=1.4142135623730950488016887242097

                With normal PBCC code:

                2^.5= 1.4142135623731
                SQR(2)= 1.4142135623731

                With EXcel:

                SQR(2)=1.4142135623731


                Some calculations with normal PBCC:

                .287933679172679
                .69093386840769
                .38835809216618
                .321225255145796
                .58504124257678
                .228199758718202
                .331446245974219
                .136864638804
                .541744172567777
                .994458125749893


                The same with C or JavaScript:

                0.287933679172679
                0.690933868407690
                0.388358092166180
                0.321225255145797
                0.585041242576780
                0.228199758718201
                0.331446245974216
                0.136864638803980
                0.541744172567673
                0.994458125749221




                SQR(2) =1.4142135623730950488016887242096980785696718753769480731766797379907324784621...
                Last edited by Ribeiro Alvo; 17 Oct 2010, 01:39 PM.

                Comment


                • #9
                  Ribeiro,
                  the idea was that you could try all 3 precision settings of the FPU by commenting out the corresponding lines in the code I posted and that might show you which precision setting the C or Java code is using.

                  With 24 bit precision we get SRQ(2)= 1.41421350228066304
                  With 53 bit precision we get SRQ(2)= 1.4142135623730952
                  With 64 bit precision we get SRQ(2)= 1.41421356237309505

                  Paul.

                  Comment


                  • #10
                    How, Paul I,m sorry.

                    I did'nt understand before.

                    I will try it again.

                    Thanks.
                    Last edited by Ribeiro Alvo; 17 Oct 2010, 07:23 PM.

                    Comment


                    • #11
                      Results with C and JavaSript in many Browsers/Computers/Windows/Mac/Linux

                      the Doubles are:

                      0.287933679172679
                      0.690933868407690
                      0.388358092166180
                      0.321225255145797
                      0.585041242576780
                      0.228199758718201
                      0.331446245974216
                      0.136864638803980
                      0.541744172567673
                      0.994458125749221

                      With your code in Double (53 bit):

                      The Doubles are:

                      .287933679172679
                      .69093386840769
                      .38835809216618
                      .321225255145796
                      .58504124257678
                      .228199758718202
                      .331446245974219
                      .136864638804
                      .541744172567777
                      .994458125749893

                      Comment


                      • #12
                        Ribeiro,

                        Try a Hlibert matrix inversion and reinversion, where the results can be better evaluated.

                        Start with a 3x3, 4x4 and so on ...
                        ' Man-Duen Choi, Tricks or treats with the Hilbert matrix
                        ' American Mathematical Monthly, Volume 90, May 1983
                        ' Determinant of inverse Hilbert matrix.
                        '
                        ' ( n) = a(n)
                        '------------------------------------------------------------
                        ' ( 0) = 1
                        ' ( 1) = 1
                        ' ( 2) = 12
                        ' ( 3) = 2160
                        ' ( 4) = 6048000
                        ' ( 5) = 266716800000
                        ' ( 6) = 186313420339200000
                        ' ( 7) = 2067909047925770649600000
                        ' ( 8) = 365356847125734485878112256000000
                        ' ( 9) = 1028781784378569697887052962909388800000000
                        ' (10) = 46206893947914691316295628839036278726983680000000000


                        1 1/2 1/3 1/4 1/5 1/6 1/7 1/8 1/9 ...
                        1/2 1/3 1/4 1/5 1/6 1/7 1/8 1/9 1/10 ...
                        1/3 1/4 1/5 1/6 1/7 1/8 1/9 1/10 1/11 ...
                        1/4 1/5 1/6 1/7 1/8 1/9 1/10 1/11 1/12 ...
                        1/5 1/6 1/7 1/8 1/9 1/10 1/11 1/12 1/13 ...
                        1/6 1/7 1/8 1/9 1/10 1/11 1/12 1/13 1/14 ...
                        1/7 1/8 1/9 1/10 1/11 1/12 1/13 1/14 1/15 ...
                        1/8 1/9 1/10 1/11 1/12 1/13 1/14 1/15 1/16 ...
                        1/9 1/10 1/11 1/12 1/13 1/14 1/15 1/16 1/17 ...
                        "The trouble with quotes on the Internet is that you can never know if they are genuine." - Abraham Lincoln.

                        Comment


                        • #13
                          I made this simple test:

                          FOR i=1 TO 20
                          PRINT i/(i+1)
                          NEXT

                          And the results are:

                          .5
                          .666666666666667
                          .75
                          .8
                          .833333333333333
                          .857142857142857
                          .875
                          .888888888888889
                          .9
                          .909090909090909
                          .916666666666667
                          .923076923076923
                          .928571428571428
                          .933333333333333
                          .9375
                          .941176470588235
                          .944444444444444
                          .947368421052632
                          .95
                          .952380952380952


                          With JavaScript:

                          The results are:

                          0.500000000000000
                          0.666666666666667
                          0.750000000000000
                          0.800000000000000
                          0.833333333333333
                          0.857142857142857
                          0.875000000000000
                          0.888888888888889
                          0.900000000000000
                          0.909090909090909
                          0.916666666666667
                          0.923076923076923
                          0.928571428571429
                          0.933333333333333
                          0.937500000000000
                          0.941176470588235
                          0.944444444444444
                          0.947368421052632
                          0.950000000000000
                          0.952380952380952

                          With this test all results are identical.

                          Comment


                          • #14
                            In the scenario above, the WORST case the results are the same to 12 decimal digits; and once again, the code used to get the decimal display value is not shown/not accounted for.

                            If you are going to work with floating point variables, you must accept that many values are approximations and rounded values, since not all decimal values can be represented exactly in the 23 (single), 54 (double) or 112 (quadruple) bits of the binary mantissa.

                            Also not accounted for: rounding/approximations in intermediate calculations. as in , " [when] I do some calculation[s] with doubles.."

                            Code not shown.
                            Last edited by Michael Mattias; 17 Oct 2010, 06:38 PM.
                            Michael Mattias
                            Tal Systems Inc.
                            Racine WI USA
                            mmattias@talsystems.com
                            http://www.talsystems.com

                            Comment


                            • #15
                              Michael...

                              ...here is the PBCC code:

                              Code:
                              FUNCTION PBMAIN
                              LOCAL n AS LONG
                              LOCAL x,a AS DOUBLE
                              x=0.256556485657464
                              a=(x/2)^(x/2)
                              FOR n=1 TO 10
                                a+=x
                                x=a*x+a
                                x-=FIX(x)
                                PRINT x
                              NEXT
                              WAITKEY$
                              END FUNCTION
                              Here is the JavaScript code:

                              Code:
                                 <SCRIPT LANGUAGE="JavaScript">
                                    var x=0.256556485657464
                                    var a=Math.pow(x/2,x/2)
                                 for (n=1; n<11; n++) {
                                    a+=x
                                    x=a*x+a
                                    x-=Math.floor(x)
                                  document.write(x.toFixed(15)+'<br>');
                                 }
                                 </SCRIPT>

                              Comment


                              • #16
                                Ribeiro,
                                the PB compiler is not preserving the FPU control register.
                                When you set it to 53bit (Double) precision and call certain functions it is being reset to 64 bit which then gives you the different answers.
                                As a temporary fix, try using this function instead of FIX:

                                Code:
                                FUNCTION FIX2(BYVAL k AS EXT) AS EXT
                                #REGISTER NONE
                                LOCAL  OriginalControlWord, NewControlWord AS INTEGER
                                
                                !fstcw OriginalControlWord  'save the original control word
                                
                                !mov ax,OriginalControlWord 'get the control word into register ax
                                !or ax, &b0000110000000000  'round toward zero (truncate)
                                !mov NewControlWord,ax      'save the new control word
                                !fldcw NewControlWord       'set the FPU to use the new control word
                                
                                !fld k                      'get the number
                                !frndint                    'truncate it to nearest integer
                                !fstp function              'store result
                                
                                !fldcw OriginalControlWord  'restore the original control word
                                
                                END FUNCTION
                                It does a bit better.

                                Paul.

                                Comment


                                • #17
                                  Code:
                                  a=(x/2)^(x/2)
                                  FOR n=1 TO 10
                                    a+=x
                                    x=a*x+a
                                    x-=FIX(x)
                                    PRINT x
                                  NEXT
                                  That code involves all kinds of significant digit overflow in both the exponentiation and the multiplication. You're lucky you have twelve decimal digit accuracy.

                                  If you need more you should think about using one those "super-precision" math libraries.

                                  What exactly is the "problem" again?
                                  Michael Mattias
                                  Tal Systems Inc.
                                  Racine WI USA
                                  mmattias@talsystems.com
                                  http://www.talsystems.com

                                  Comment


                                  • #18
                                    Michael

                                    That code involves all kinds of significant digit overflow in both the exponentiation and the multiplication. You're lucky you have twelve decimal digit accuracy.

                                    If you need more you should think about using one those "super-precision" math libraries.

                                    What exactly is the "problem" again?
                                    The question (not a problem) is not more accuracy. The question is, as I said in the OP, the compatibility between C or JavaScritp and PBCC, and, if it is a way to obtain equal results, making some code in PBCC. I think Paul Dixon already catch the OP. Ok?

                                    Comment


                                    • #19
                                      Paul...

                                      ...I tested the code above, calling FIX2 with DOUBLES or EXT, the values remains the same as before.

                                      Thanks anyway.

                                      Comment


                                      • #20
                                        Ribeiro,
                                        the same? You must be doing something wrong.
                                        Here's the full compilable program:
                                        Code:
                                        'PBCC5 program
                                        #COMPILE EXE
                                        #DIM ALL
                                        
                                        FUNCTION PBMAIN () AS LONG
                                        #REGISTER NONE   'the control words mustn't be register variables
                                        
                                        LOCAL OriginalControlWord, NewControlWord AS INTEGER    'control word is a 16 bit register
                                        LOCAL PrecisionRequired AS INTEGER
                                                                          
                                        'PrecisionRequired = &b0000000000000000    'single precision 24bit
                                        'PrecisionRequired = &b0000000100000000    'unused
                                        PrecisionRequired = &b0000001000000000    'double precision 53bit
                                        'PrecisionRequired = &b0000001100000000    'extended precision 64bit
                                        
                                        
                                        !fstcw OriginalControlWord  'save the original control word
                                        
                                        !mov ax,OriginalControlWord 'get the control word into register ax
                                        !and ax,&hf0ff              'mask off the precision and rounding bits
                                        !or ax, PrecisionRequired   'set precision as required
                                        !mov NewControlWord,ax      'save the new control word
                                        !fldcw NewControlWord       'set the FPU to use the new control word
                                        
                                        
                                        'put code here
                                        LOCAL n AS LONG
                                        LOCAL x,a AS DOUBLE
                                        
                                        x=0.256556485657464#
                                        a=(x/2)^(x/2)
                                        
                                        FOR n=1 TO 10
                                        
                                          a+=x
                                          x=a*x+a
                                          x-=FIX2(x)
                                          PRINT x
                                          
                                        NEXT
                                        
                                        WAITKEY$
                                        
                                        !fldcw OriginalControlWord   'Restore to original condition
                                               
                                        END FUNCTION
                                        
                                        
                                        FUNCTION FIX2(BYVAL k AS EXT) AS EXT
                                        #REGISTER NONE
                                        LOCAL  OriginalControlWord, NewControlWord AS INTEGER
                                        
                                        !fstcw OriginalControlWord  'save the original control word
                                        
                                        !mov ax,OriginalControlWord 'get the control word into register ax
                                        !or ax, &b0000110000000000  'round toward zero (truncate)
                                        !mov NewControlWord,ax      'save the new control word
                                        !fldcw NewControlWord       'set the FPU to use the new control word
                                        
                                        !fld k                      'get the number
                                        !frndint                    'truncate it to nearest integer
                                        !fstp function              'store result
                                        
                                        !fldcw OriginalControlWord  'restore the original control word
                                        
                                        END FUNCTION
                                        and here's the output it gives:
                                        .287933679172679
                                        .69093386840769
                                        .38835809216618
                                        .321225255145797
                                        .58504124257678
                                        .228199758718201
                                        .331446245974216
                                        .13686463880398
                                        .541744172567672
                                        .994458125749221
                                        That's near identical to the C/Java results you gave.

                                        Paul.

                                        Comment

                                        Working...
                                        X