Announcement

Collapse
No announcement yet.

Accuracy falls off

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

  • Bob Zale
    replied
    Originally posted by Michael Mattias:
    In your post, I cannot really tell if you are suffering from "bad math," "bad printed output" or both.
    The answer is E) None of the above.

    Repeat after me, Michael... {smile} Single precision floats as function parameters offer approximately 7 decimal digits of precision. That's insufficient for this application.

    Regards,

    Bob


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

    Leave a comment:


  • Michael Mattias
    replied
    Do not confuse the internal numerical accuracy of arithmetic with the string representation of operands or results.

    FORMAT$, USING$ and STR$ are independent functions with their own 'accuracy' rules.

    In your post, I cannot really tell if you are suffering from "bad math," "bad printed output" or both.

    MCM


    Leave a comment:


  • Bob Zale
    replied
    Originally posted by Mel Bishop:
    $if 0
    And, yes Bob, I did read the book and chapter. This program
    should work.

    No, it actually shouldn't work, and I'm sure it doesn't work. That's because the value is being rounded to a Single Precision Float as a function parameter. The chapter on Floating Point gives a pretty good description of what happens when the limits of the mantissa are exceeded. Change that Single Float param to something with a larger mantissa.

    Best of luck with this!

    Bob Zale
    PowerBASIC Inc.


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

    Leave a comment:


  • RM Green
    replied
    Oh, OK. You're talking about LBAs not FAT entries. I guess you
    have defined a UDT for the LBA parameter buffer with the
    starting LBA as a QUAD. You can just plug your LBA right in
    there, no conversion is necessary.

    Bob

    Leave a comment:


  • Mel Bishop
    replied
    $if 0
    Okay, here's a complete test program I wrote to find out where
    the trouble beings. Everything is fine up to it processing
    16,777,216. The rounding errors occur when it tries to process
    16,777,217. The number 16,777,217 falls far short of the maximum
    as defined being a quad-number.

    And, yes Bob, I did read the book and chapter. This program
    should work.

    Mr. Green, I tried your hex routine and it stopped at exactly
    the same place. No luck with that one.

    Anybody got any other ideas? Tnx in advance.

    $endif
    Code:
    	$lib all off
            $error all on
    	color 14,1
    	cls
            dim sector as shared quad
            dim temp   as shared quad
            dim te     as shared quad
            dim back   as shared quad
            dim test1  as shared quad
            dim test2  as shared quad
            dim lp     as shared quad
            dim c1     as shared quad
            dim c2     as shared quad
            dim c3     as shared quad
            dim c4     as shared quad
            dim c5     as shared quad
            dim c6     as shared quad
            dim c7     as shared quad
            dim c8     as shared quad
    
            dim n1     as shared quad
            dim n2     as shared quad
            dim n3     as shared quad
            dim n4     as shared quad
            dim n5     as shared quad
            dim n6     as shared quad
            dim n7     as shared quad
    
            dim tt   as shared quad
            n7 = 256 ^ 7
            n6 = 256 ^ 6
            n5 = 256 ^ 5
            n4 = 256 ^ 4
            n3 = 256 ^ 3
            n2 = 256 ^ 2
            n1 = 256 ^ 1
    
            f$ = "###,###,###,###,###,###"		'
                                                    '
    	locate 2, 5 : print;"  Original:";      '
            locate 3, 5 : print;"Calculated:";      '
            lp = 16500000                           ' Preset the original number
                                                    '
    	do                                      '
            incr lp                                 '
            test1 = lp                              ' Substitute
            locate 2,20                             '
            print;using$(f$,test1);                 ' display original number
                                                    '
            a$ = quadword8$(bycopy lp)              ' Calc the 8-bit string
                                                    '
            locate 5,20                             '
            for x = 1 to len(a$)                    ' Disp 8-bit string
            print;using$("###  ",asc(mid$(a$,x,1)));'
            next x                                  '
                                                    '
            test2 = back(bycopy a$)                 ' Convert string back to
            locate 3,20                             ' (?original?) number
            print;using$(f$,test2);                 '
                                                    '
    	if test1 <> test2 then call pause       ' Compare & pause if not a
                                                    ' match.
            if inkey$ = chr$(27) then exit loop     '
    	loop                                    '
            end                                     '
                                                    '
    sub pause                                       '
    	while instat=0:wend                     '
            an$ = inkey$                            '
            if an$ = chr$(27) then end              '
            end sub                                 '
                                                    '
    function quadword8$(temp)                       '
    
    	c8 = int(temp / n7) : temp = temp - c8 * n7
    	c7 = int(temp / n6) : temp = temp - c7 * n6
    	c6 = int(temp / n5) : temp = temp - c6 * n5
    	c5 = int(temp / n4) : temp = temp - c5 * n4
    	c4 = int(temp / n3) : temp = temp - c4 * n3
    	c3 = int(temp / n2) : temp = temp - c3 * n2
    	c2 = int(temp / n1)
            c1 = temp - c2 * 256
    
    	function = chr$(c1) + chr$(c2) + chr$(c3) + chr$(c4) + _
                       chr$(c5) + chr$(c6) + chr$(c7) + chr$(c8)
    	end function
    
    
    function back(temp$)
    
            te = 0
    
    	te = asc(mid$(temp$,1,1))
    	te = te + asc(mid$(temp$,2,1)) * 256 ^ 1
    	te = te + asc(mid$(temp$,3,1)) * 256 ^ 2
    	te = te + asc(mid$(temp$,4,1)) * 256 ^ 3
    	te = te + asc(mid$(temp$,5,1)) * 256 ^ 4
    	te = te + asc(mid$(temp$,6,1)) * 256 ^ 5
    	te = te + asc(mid$(temp$,7,1)) * 256 ^ 6
    	te = te + asc(mid$(temp$,8,1)) * 256 ^ 7
    	function = te
    
    	end function
    ------------------


    [This message has been edited by Mel Bishop (edited January 15, 2003).]

    Leave a comment:


  • Mel Bishop
    replied
    Originally posted by RM Green:
    ...Forgive my curiosity, but what is the purpose of the
    conversion and why an 8 byte string instead of 4?
    FAT style string. Not necessairly the FAT itself.

    I am trying to read hard drive LBA sectors and, apparently, the
    info packet requires an 8-byte string to read which sector. I
    could be wrong but I haven't got that far to find out. I really
    like experimenting, especially after I've backed up my hard
    drive. (killing two birds with one stone so to speak).

    I'll give your idea a try and see what happens. Thanks.


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


    [This message has been edited by Mel Bishop (edited January 15, 2003).]

    Leave a comment:


  • RM Green
    replied
    Mel,

    Here's another way to do it and preserve accuracy.

    $lib all off
    $error all on
    color 14,1
    cls
    dim sector as shared quad
    f$ = "###,###,###,###,###,###"

    for sector = 1 to 256 ^ 4 - 1
    locate 3,10
    print;using$(f$,sector);
    c$ = ""

    locate 7,10
    a$ = hex$(sector)
    if len(a$) < 32 then a$ = string$(32-len(a$),"0")+a$
    for i% = 31 to 17 step -2
    b$="&H"+mid$(a$,i%,2)
    print;using$("### ",val(b$));
    c$=c$+chr$(val(b$))
    next i%

    locate 5,10 rint "Quad String: ";c$

    if inkey$ = chr$(27) then exit for

    next sector

    end

    These are supposed to represent FAT cluster numbers? Forgive my
    curiosity, but what is the purpose of the conversion and why an
    8 byte string instead of 4?

    Bob


    [This message has been edited by RM Green (edited January 15, 2003).]

    Leave a comment:


  • Michael Mattias
    replied
    I think quadWord(temp as QUAD) might be a little easier as:

    Code:
    FUNCTION = MKL$(Temp \ &h0100000000) + MKL$(temp MOD &h0100000000)
    (quad as string = least significant long + most significant long)

    Also note you should never need floating point to work with these

    And a still easier way
    Code:
    UNION Foo
     Q AS QUAD
     S AS STRING * 8
    END UNION
    
    DIM W AS Foo
     W.Q = temp (or other quad value)
    
     PRINT "string represention of temp is " & W.S
    Convert back?
    Code:
    LSET W.S = (eight-byte string)
    PRINT "Value of temp is" & STR$(W.Q)
    MCM


    [This message has been edited by Michael Mattias (edited January 14, 2003).]

    Leave a comment:


  • Bob Zale
    replied
    Mel,

    Single precision floats have all the range you need, but only seven (7) significant digits. Use Double Precision for 16-digit or Extended precision for 18-digit. Also, you really should read the chapter on Floating Point in your manuals. It provides everything you need to know. Best of luck!

    Bob Zale
    PowerBASIC Inc.


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

    Leave a comment:


  • Paul Dixon
    replied
    Mel,
    I'd guess, without trying it out, that you're using lower precision variables in the calculation of the 17 digit number.
    Try DIMing all the variables in the subroutine as QUADs instead of reals in order to avoid the rounding.

    Paul.


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

    Leave a comment:


  • Mel Bishop
    started a topic Accuracy falls off

    Accuracy falls off

    I developed the below code to convert a number into an 8-digit
    string such as would be found in a FAT. All is well until it
    reaches some point. I haven't been able to find the exact point,
    but when it reaches this point, it gives erronious results. For
    example, 61,555,599 and 61,555,600 will return the same string,
    i.e. 144 67 171 3.

    According to the book, PB3.5 can digest numbers with 18-digits
    of accuracy and 256 ^ 7 (the biggest I want it to hande here)
    produces a 17-digit (BIG) number.

    Any idea as to what's happening or what I am mis-reading?

    Code:
    	$lib all off
            $error all on
    	color 14,1
    	cls
            dim sector as shared quad
    
            f$ = "###,###,###,###,###,###"
    
    	for sector = 0 to 256 ^ 4 - 1
            locate 3,10
            print;using$(f$,sector);
    
            y$ = quadword8$(bycopy sector)
    	locate  5,10 : print;"Quad Word: ";y$
    
            locate  7,10
            for x = 1 to len(y$)
            print;using$("###  ",asc(mid$(y$,x,1)));
            next x
            if inkey$ = chr$(27) then exit for
            next sector
    
            end
    
    function quadword8$(temp)
    	tt = 256
    	c8 = int(temp / (tt ^ 7)) : temp = temp - c8 * tt ^ 7
    	c7 = int(temp / (tt ^ 6)) : temp = temp - c7 * tt ^ 6
    	c6 = int(temp / (tt ^ 5)) : temp = temp - c6 * tt ^ 5
    	c5 = int(temp / (tt ^ 4)) : temp = temp - c5 * tt ^ 4
    	c4 = int(temp / (tt ^ 3)) : temp = temp - c4 * tt ^ 3
    	c3 = int(temp / (tt ^ 2)) : temp = temp - c3 * tt ^ 2
    	c2 = int(temp /  tt)
            c1 = temp - c2 * tt
    
    	function = chr$(c1) + chr$(c2) + chr$(c3) + chr$(c4) + _
                       chr$(c5) + chr$(c6) + chr$(c7) + chr$(c8)
    	end function

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


    [This message has been edited by Mel Bishop (edited January 14, 2003).]
Working...
X