Announcement

Collapse
No announcement yet.

A Frac problem..

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

  • Aldo Vitagliano
    replied
    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>

    Leave a comment:


  • Tom Hanlin
    replied
    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

    Leave a comment:


  • Bern Ertl
    replied
    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

    Leave a comment:


  • Bern Ertl
    replied
    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).]

    Leave a comment:


  • Edwin Knoppert
    replied
    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.


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

    Leave a comment:


  • Aldo Vitagliano
    replied
    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>

    Leave a comment:


  • David J Walker
    replied
    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!

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

    Leave a comment:


  • Aldo Vitagliano
    replied
    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>

    Leave a comment:


  • Michael Mattias
    replied
    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."

    Leave a comment:


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



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

    Leave a comment:


  • Edwin Knoppert
    replied
    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

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

    Leave a comment:


  • Lance Edmonds
    replied
    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>

    Leave a comment:


  • Edwin Knoppert
    started a topic A Frac problem..

    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

    ------------------
Working...
X