Announcement

Collapse
No announcement yet.

A Frac problem..

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

  • A Frac problem..

    Run this one..

    Code:
    #Compile Exe
     
    Function PbMain
     
        Dim T As String
        Dim D As Double
     
        T = "123456789.1"
        d = 123456789.1#
     
        MsgBox Format$( Val( T ) ) & $CRLF _
        & Format$( Frac( Val( T ) ) ) & $CRLF _
        & Str$( Frac( d ) )
     
    End Function

    ------------------
    hellobasic

  • #2
    And...?

    Seriously, floating point variables can only represent a limited (finite) number of real numbers (for which there are an infinite number).

    If you want to display the value with a smaller number of decimal places, try specifying the digits in the STR$() function.

    For example,
    Code:
    MSGBOX STR$(FRAC(VAL(T))[b],2[/b]) & STR$(FRAC(d)[b],2[/b])
    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    Lance
    mailto:[email protected]

    Comment


    • #3
      The point is that the value presented is no longer .1 but (i don't know...)
      I retrieve the frac now by searching or "."

      This problem looks a lot of my earlier problem doubles <> singles
      I had to add # or ! to get the correct value.
      There's no way to add # to a Frac() function

      ------------------
      hellobasic

      Comment


      • #4
        If precision is necessary, you might consider using the Currency (@, CUR) or
        Extended Currency (@@, CUX) data types....



        ------------------
        Bernard Ertl
        Bernard Ertl
        InterPlan Systems

        Comment


        • #5
          There's no way to add # to a Frac() function
          Patient, holding his right arm up in the air to demonstrate: "Doctor, when I do this, it hurts."

          Doctor: "Then don't do that."

          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            Three digits of precision can be recovered at no extra cost
            by ensuring full use of the 80 bits of the FPU, as in the following code (adapted to PBCC)
            (ASM code posted by Lance in the FAQ forum):

            Code:
            FUNCTION PBMAIN ()
            
               #REGISTER NONE
            '--------------------------------------------------------
            '.... This code ensures full use of 80X87 in 80 bits mode
               xyz& = 0
               ASM fstcw xyz&
               ASM OR xyz&, &B0000001100000000&
               ASM fldcw xyz&
            '--------------------------------------------------------
            
               DIM T AS STRING
               DIM D AS DOUBLE
               T = "123456789.1"
               d = 123456789.1#
               PRINT FORMAT$( VAL( T ) )
               PRINT " "; FORMAT$( FRAC( VAL( T ) ) ) ' now executed in 80 bits
               PRINT STR$( FRAC( d ) )
               WAITKEY$
            
            END FUNCTION


            ------------------
            Aldo Vitagliano
            mailto:[email protected][email protected]</A>
            Aldo Vitagliano
            alvitagl at unina it

            Comment


            • #7
              Go and find a Sinclair Spectrum (or Timex something or other in USA)

              Enter the following line of code:

              10 PRINT 1/2 = 0.5, 0.5 = 1/2

              If you trust anything but integer arithmetic after that, you deserve
              all you get!

              ------------------

              Comment


              • #8
                The problem raised by Edwin has two components.

                1st) Precision (number of significant digits) is ALLWAYS lost when performing differences, e.g.:
                Code:
                123456789.1000000 -  '16 significant digits if DOUBLE
                123456789         =   'exact integer
                ___________________
                        0.1000000    '7 significant digits in the result of the FRAC function
                                     'all extra digits are meaningless
                2d) The decimal fraction 1/10 (as most decimal fractions) cannot be represented
                exactly in binary format, so it is rounded to the next binary fraction.
                Rounding makes it so that when 0.1000000 (with 7 significant digits) is rounded to the next binary fraction
                and PRINTED with 15 significant digits, the result is 0.099999994039...
                If the code posted by Edwin is tried with the number
                123456789.125
                then the fractional part corresponds to an exact binary fraction and the result will be exact.

                Regards




                ------------------
                Aldo Vitagliano
                mailto:[email protected][email protected]</A>
                Aldo Vitagliano
                alvitagl at unina it

                Comment


                • #9
                  Aldo,
                  You described my problem !
                  I.o.w. it seems in pb is not possible to use the frac() this way.
                  ??
                  I don't like solutions like defint or asm to fix the processor.
                  They can not be trusted.


                  ------------------
                  hellobasic

                  Comment


                  • #10
                    Edwin,

                    How many digits of precision do you require?

                    Code:
                    #Compile Exe
                    
                    
                    Function PbMain
                    
                    
                        Dim T As String
                        Dim D As CUX
                    
                    
                        T = "123456789.1"
                        d = [email protected]@
                    
                    
                        MsgBox Format$( Val( T ) ) & $CRLF _
                        & Format$( Frac( Val( T ) ) ) & $CRLF _
                        & Str$( Frac( d ) )
                    
                    
                    End Function

                    ------------------
                    Bernard Ertl



                    [This message has been edited by Bern Ertl (edited July 09, 2001).]
                    Bernard Ertl
                    InterPlan Systems

                    Comment


                    • #11
                      Sorry,

                      I jumped the gun. Frac() with a CUR/CUX var still does not produce 0.1.

                      But the following does get you what you wanted...

                      Code:
                      #COMPILE EXE
                      
                      
                      FUNCTION PBMAIN
                      
                      
                          DIM T AS STRING
                          DIM D AS DOUBLE
                      
                      
                          T = "123456789.1"
                          d = 123456789.1#
                      
                      
                          MSGBOX FORMAT$( VAL( T ) ) & $CRLF _
                          & FORMAT$( CCUX( FRAC( VAL( T )) ) ) & $CRLF _
                          & STR$( CCUX( FRAC( d )) )
                      
                      
                      END FUNCTION
                      ------------------
                      Bernard Ertl
                      Bernard Ertl
                      InterPlan Systems

                      Comment


                      • #12
                        It may be useful to note that you're comparing values of different numeric types,
                        here, which may be causing some of the confusion. Think:

                        T = "123456789.1#" ' note the #

                        ------------------
                        Tom Hanlin
                        PowerBASIC Staff

                        Comment


                        • #13
                          edwin,
                          if the asm code posted by lance at http://www.powerbasic.com/support/pb...hread.php?t=45
                          cannot be trusted, then the whole use of extended precision variables
                          would be useless (except when performing the four basic arithmetic operations)
                          i believe it can be trusted, and i always put it at the beginning of a program
                          when high precision is required (even if i don't use ext variables).
                          i really hope to be right!
                          there is no way of squeezing out of a fractional part more significant digits
                          than the difference 19-(number of digits of the integer part).
                          the disturbing roundoff effect coming from the binary fractions when they are
                          converted to decimal can be removed by a "flexible" roundoff,
                          as done by the following code.

                          Code:
                          declare function fracx(x##) as double
                          
                          function pbmain()
                          
                              #register none
                          '--------------------------------------------------------
                          '.... this code ensures full use of 80x87 in 80 bits mode
                              xyz& = 0
                              asm fstcw xyz&
                              asm or xyz&, &b0000001100000000&
                              asm fldcw xyz&
                          '--------------------------------------------------------
                              do
                                 line input var$
                                 if var$=" then exit do
                                 print fracx(val(var$))
                              loop
                              
                          end function
                          
                          function fracx(x as ext) as double
                             n&=19-fix(log10(1+abs(x)))
                             fracx=round(frac(x),n&)
                          end function
                          if somebody knows how to count the digits which precede the decimal point in
                          a way faster than using a log10 function (and without using string functions, which are even slower),
                          please let me known.

                          bern,

                          currency and extended currency variables are fixed point and limited to a fixed number of decimal places.
                          floating point bcd (binary coded decimals) would be much better, but unfortunately they seem to be implemented
                          only in pbdos, and not in pbcc or pbdll (could be a wish for the wishlist !)

                          regards

                          ------------------
                          aldo vitagliano
                          mailto:[email protected][email protected]</a>
                          Aldo Vitagliano
                          alvitagl at unina it

                          Comment

                          Working...
                          X