Announcement

Collapse
No announcement yet.

Accuracy falls off

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

  • 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).]
    There are no atheists in a fox hole or the morning of a math test.
    If my flag offends you, I'll help you pack.

  • #2
    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.


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

    Comment


    • #3
      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.


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

      Comment


      • #4
        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).]
        Michael Mattias
        Tal Systems Inc. (retired)
        Racine WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          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).]

          Comment


          • #6
            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).]
            There are no atheists in a fox hole or the morning of a math test.
            If my flag offends you, I'll help you pack.

            Comment


            • #7
              $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).]
              There are no atheists in a fox hole or the morning of a math test.
              If my flag offends you, I'll help you pack.

              Comment


              • #8
                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

                Comment


                • #9
                  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.


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

                  Comment


                  • #10
                    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


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

                    Comment


                    • #11
                      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


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

                      Comment

                      Working...
                      X