Announcement

Collapse
No announcement yet.

VAL rounds a variable

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

  • VAL rounds a variable

    Can someone tell my why VAL is rounding a variable in the following code?

    <br><br>
    Code:
    #COMPILE EXE
    DEFLNG A-Z
    
    FUNCTION PBMAIN () AS LONG
    
        X$ = "2.6"
        Y = VAL(X$)
        
        PRINT Y             'why is Y rounded to 3 when its assigned to a variable,
        PRINT VAL(X$), X$   'but the original retains 2.6?
        
        WAITKEY$
                                             
    END FUNCTION

  • #2
    DEFLNG A-Z... one of the most terrible BASIC statements ever..

    Y is a long integer which can not hold decimals.
    Local Y as Double would do..
    VAL() returns an Extended-currency (@@)
    Last edited by Edwin Knoppert; 9 Jun 2008, 03:36 PM.
    hellobasic

    Comment


    • #3
      removed
      Last edited by Paul Purvis; 11 Jun 2008, 01:45 AM.
      p purvis

      Comment


      • #4
        For money?

        How about...
        Code:
        N = ROUND(M, 2)
        ?????
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          Not using # or @@ in the values .5 and 10 may have impact on results!
          Eventually make it a variable or assign the symbols.

          I also had trouble with color calculation where the result is a quad.

          2 ^ ... for example is not good enough and is an overflow.
          hellobasic

          Comment


          • #6
            my math is broken
            i need to multiply F times the number of decmials of variable B
            see the line "my math is broken"
            this program does not work yet for negative numbers

            i am trying to round for fraction of 5 up
            it does not have be money either

            just another rounding routine

            Code:
            #COMPILE EXE
            #DIM ALL
            
            FUNCTION MONEYROUND(BYVAL A AS EXT,BYVAL B AS LONG) AS EXT
            LOCAL D AS QUAD
            LOCAL C AS QUAD
            LOCAL E AS QUAD
            LOCAL F AS QUAD
            D=(10^(B+2))
            E=(FIX(((FIX(D*A)) +(SGN(A)*(5&&)))))\10
            PRINT E
            F=((E-(E-FIX(E*.1)*10))\10)*10
            PRINT F
            IF E-F>4 THEN F=F+10
            PRINT F
            FUNCTION=F/(FIX(10^(b+1)))'*SOMETHING HERE    my math is broken
            END FUNCTION
            
            FUNCTION PBMAIN () AS LONG
            LOCAL M AS EXT
            LOCAL N AS EXT
            M=12.15555
            N=MONEYROUND(M,4)
            PRINT N
            WAITKEY$
            
            END FUNCTION
            added:
            removed variable D and C, and placed code for negative numbers

            THIS IS STILL CODE BEING TESTED

            Code:
            #COMPILE EXE
            #DIM ALL
            
            FUNCTION MONEYROUND(BYVAL A AS EXT,BYVAL B AS LONG) AS EXT
            LOCAL E AS QUAD
            LOCAL F AS QUAD
            LOCAL isign AS LONG
            isign=SGN(a)
            IF isign=-1 THEN a=ABS(a)
            E=(FIX(((FIX((10^(B+2))*A))+5&&)))\10
            PRINT E
            F=((E-(E-FIX(E*.1)*10))\10)*10
            PRINT F
            IF E-F>4 THEN F=F+10
            PRINT F
            'if statement to allow for a negative number
            IF isign=-1 THEN
              FUNCTION=(F/(FIX(10^(b+1))))*-1'*SOMETHING HERE    my math is broken
              ELSE
              FUNCTION=F/(FIX(10^(b+1))) '*SOMETHING HERE    my math is broken
            END IF
            END FUNCTION
            
            FUNCTION PBMAIN () AS LONG
            LOCAL M AS EXT
            LOCAL N AS EXT
            M=-12.15555
            N=MONEYROUND(M,4)
            PRINT N
            WAITKEY$
            
            END FUNCTION
            Last edited by Paul Purvis; 12 Jun 2008, 01:21 AM.
            p purvis

            Comment


            • #7
              Paul, this wasn't as straightforward as I was thinking it would be. yow. Also, this rounds negatives more negative. Is that correct? It can be modified easily to round them less negative too.

              see new code here

              Code:
              #COMPILE EXE
              #DIM ALL
              
              FUNCTION roundUp(BYVAL A AS EXT, BYVAL B AS LONG) AS EXT
                 LOCAL x AS EXT, neg AS LONG
              
              'more bugs found, needs more testing. Will repost later...
              Reposted at link above 
              [URL="http://www.powerbasic.com/support/pbforums/showthread.php?p=287657#post287657"]here[/URL]
              
              END FUNCTION
              Last edited by John Gleason; 12 Jun 2008, 06:51 PM. Reason: found a bug, fixed it in red

              Comment


              • #8
                Rounding

                Since VAL($) will give an extended Currency value why not use it directly ?
                The rounding will be automatic and always right for both positive and negative fractions.

                Code:
                #COMPILE EXE
                FUNCTION PBMAIN () AS LONG
                
                 m$="123.4567"
                 n$="-123.4567"
                 [email protected]@=VAL(m$)
                 [email protected]@=VAL(n$)
                 PRINT [email protected]@,[email protected]@
                 WAITKEY$
                
                END FUNCTION
                Old QB45 Programmer

                Comment


                • #9
                  i first was working with the dollars and it would be great(fantastic) to have a money rounding function, but it seemed to me being a younger pb programmer(it is nice to be younger at something) that maybe i should try my hand at floating point rounding for many different financial math routines.
                  there are many math functions dealing in the money that have to be very correct such as the APR on borrowed money that is Federally regulated and the there is not much tolerance in the results that can be computed.
                  and a lot of those computations that can not be done with a currency variable, or at least, i would think so from previous experience in calculating the APR.
                  also there are also laws with certain limits that can not be exceeded in many financial situations and i can see where using currency only values in calculations would make some results unacceptable.

                  i have been so brain dead from working on too many projects, i need to take the F variable and reduced it to certain decimal places after getting it to a whole number with out a loop.

                  for those looking at my math i could possibly had used the MOD statement to get the 1st digit between 0 and 9, but without testing, i thought maybe some other math might have been faster, but maybe not.

                  so can some body help with this

                  i might of just found the fix
                  i need somebody to shoot this routine out the sky
                  i placed code that should allow for negative numbers

                  FUNCTION=F/(FIX(10^(b+1)))

                  i made the change above.
                  Last edited by Paul Purvis; 12 Jun 2008, 12:59 AM.
                  p purvis

                  Comment


                  • #10
                    GUY
                    sorry
                    your function will fail
                    using 123.455, the 5 is going to be the problem and i did not understand the 10 as mentioned earlier until today

                    values returned should be 123.46
                    but you will get will be 123.45

                    Code:
                    #COMPILE EXE
                    FUNCTION PBMAIN () AS LONG
                    
                     m$="123.455"
                     n$="-123.455
                     [email protected]@=VAL(m$)
                     [email protected]@=VAL(n$)
                     PRINT [email protected]@,[email protected]@
                     WAITKEY$
                    
                    END FUNCTION
                    added:
                    my code failed too
                    use 12.1149
                    rounded to two decimal, resulting with 12.12
                    Last edited by Paul Purvis; 12 Jun 2008, 01:34 AM.
                    p purvis

                    Comment


                    • #11
                      I do some floating point rounding in this post:
                      Telco Benchmark Program 5-20-04
                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #12
                        Paul, it's funny but that's the reason my code was failing too, the 49's rounding up. I finally got it to work in every case of two decimal places. Now to get those pesky other few thousand.

                        Comment


                        • #13
                          Rounding

                          Paul,

                          What version of PBCC are you using ?
                          My rounding results are correct.

                          Code:
                          #COMPILE EXE
                          FUNCTION PBMAIN () AS LONG
                          
                           m$="123.455": n$="-123.455": o$="12.1149"
                           [email protected]@=VAL(m$): [email protected]@=VAL(n$): [email protected]@=VAL(o$)
                           PRINT [email protected]@,[email protected]@,[email protected]@
                           'Result shown are : 123.46  -123.46  12.11
                           WAITKEY$
                          
                          END FUNCTION
                          Old QB45 Programmer

                          Comment


                          • #14
                            Originally posted by Michael Mattias View Post
                            I do some floating point rounding in this post:
                            Telco Benchmark Program 5-20-04
                            Michael, for p = ROUND(p,2), is it a compiler bug that even digits preceding the 5 round down, for instance, .185 rounds to .18, and odds round up, eg. .475 rounds to .48? PB ver. 8.04 differs from your .065 rounding to .07 result (8.04 rounds it to .06)

                            Comment


                            • #15
                              Guy, try the following:
                              Code:
                              #COMPILE EXE
                              FUNCTION PBMAIN () AS LONG
                              
                               m$="123.465": n$="-123.465": o$="12.1149"
                               [email protected]@=VAL(m$): [email protected]@=VAL(n$): [email protected]@=VAL(o$)
                               PRINT [email protected]@,[email protected]@,[email protected]@
                               'Result shown are : 123.46  -123.46  12.11
                               WAITKEY$
                              
                              END FUNCTION
                              Results should be 123.47 -123.47 12.11

                              Comment


                              • #16
                                I'm Not sure this is relevant.

                                James

                                Comment


                                • #17
                                  James to me, that was very helpful.
                                  i guess with what i am reading.
                                  the only way for me then maybe is just to walk the digits furtherest from the right back to the desired digit.
                                  p purvis

                                  Comment


                                  • #18
                                    Redo of earlier post with extensive test code built in. PB ver. 8.04. Sry, I don't have CC. Try your technique Paul, and the two versions can be tested against each other for accuracy.
                                    Code:
                                    #COMPILE EXE
                                    #DIM ALL
                                    '-----------------------------------------------------------------------
                                    'Rounds last digit of 5 always up, eg. 24.425 rounds to 24.43 if B = 2. Runs in ~ 415 ticks
                                    '-----------------------------------------------------------------------
                                    FUNCTION roundUp(BYVAL a AS EXT, BYVAL b AS LONG) AS EXT
                                       LOCAL x, y AS EXT, neg AS LONG
                                       LOCAL z AS QUAD       '<< has to be quad! if it's EXT, z MOD 5 = 5 occasionally. Don't know why.
                                                                
                                       IF a < 0 THEN
                                          a = -a
                                          neg = 1
                                       END IF
                                    
                                       x = ROUND(a, b)      'in 8.04 (and probably most recent CC ver.) round to even, or banker's rounding
                                       IF x >= a THEN
                                          IF neg = 1 THEN x = -x
                                          FUNCTION = x
                                          EXIT FUNCTION
                                       END IF
                                    
                                       y = 10 ^ (b + 1)
                                       z = a * y            'move decimal point to end
                                                       
                                       IF z MOD 5 = 0 THEN  'see if last digit is a 5
                                          x = z + 5         'round up if it is
                                          IF neg = 1 THEN
                                             FUNCTION = ROUND(-x / y, b)
                                          ELSE
                                             FUNCTION = ROUND( x / y, b)
                                          END IF
                                          EXIT FUNCTION
                                       END IF
                                    
                                       IF neg = 1 THEN
                                          FUNCTION = -x     'use from ROUND calculation already done above
                                       ELSE
                                          FUNCTION = x
                                       END IF
                                    
                                    END FUNCTION
                                    
                                    FUNCTION PBMAIN () AS LONG
                                       LOCAL M AS EXT, rot, iter, ii AS LONG
                                       LOCAL n AS QUAD
                                       RANDOMIZE
                                                      
                                       FOR ii = 1 TO 100000000      'test a hundred million roundUp's against ROUND's to be quite sure it is correct
                                          INCR rot                  'rotator
                                                                    'note: use only 1 of following 2 lines at a time for +/- testing.
                                          M = ROUND(RND * 100, rot) 'get a random  number with rotator mantissa digits, eg. if rot = 3,  46.321 might result
                                    '     M = ROUND(RND * -100, rot)'get a -random number with rotator mantissa digits, eg. if rot = 3, -46.321 might result
                                          IF (iter AND &h0ffffff) = 0 THEN BEEP 'beep occasionally to let you know it's testing.
                                          INCR iter
                                                                             'note: use only 1 of following 2 lines at a time for +/- testing.
                                          IF roundUp(M, rot - 1) <= M THEN   'use to test for positive number errors
                                    '     IF roundUp(M, rot - 1) > M THEN    'use to test for negative number errors
                                             n = 10 ^ (rot)
                                             IF M * n MOD 10 < 5.5 AND M * n MOD 10 > 4.5 THEN    'if last digit is a 5 then function has an error!
                                                ? STR$(M - roundUp(M, rot-1), 18) & $CRLF & STR$(M, 18) & $CRLF & STR$(roundUp(M, rot-1), 18) & _
                                                  $CRLF & STR$(ROUND(M, rot-1), 18) & $CRLF & STR$(iter) & $CRLF & STR$(rot),48,"Error1"
                                             ELSEIF ROUND(M, rot - 1) <> roundUp(M, rot - 1) THEN 'they otherwise should be =, or again it's a error!
                                                ? STR$(M - roundUp(M, rot-1), 18) & $CRLF & STR$(M, 18) & $CRLF & STR$(roundUp(M, rot-1), 18) & _
                                                  $CRLF & STR$(ROUND(M, rot-1), 18) & $CRLF & STR$(iter) & $CRLF & STR$(rot),48,"Error2"
                                             END IF
                                         END IF
                                        IF rot = 16 THEN rot = 0
                                       NEXT
                                    END FUNCTION

                                    Comment


                                    • #19
                                      Rounding

                                      Paul,

                                      You are right, my function did fail with those numbers.
                                      I tought extended currency could do it automaticaly but I was wrong.

                                      Here is a technique I used all the time with QB45 to round double precision numbers.

                                      Code:
                                      #COMPILE EXE
                                      FUNCTION PBMAIN () AS LONG
                                      
                                      m$="123.465": n$="-123.465": o$="12.1149"
                                      [email protected]@=ABS(VAL(m$))+.0001: IF VAL(m$)<0 THEN [email protected]@[email protected]@*-1
                                      [email protected]@=ABS(VAL(n$))+.0001: IF VAL(n$)<0 THEN [email protected]@[email protected]@*-1
                                      [email protected]@=ABS(VAL(o$))+.0001: IF VAL(o$)<0 THEN [email protected]@[email protected]@*-1
                                      
                                       PRINT [email protected]@,[email protected]@,[email protected]@
                                       'Result shown are : 123.47  -123.47  12.11
                                       WAITKEY$
                                      
                                      END FUNCTION
                                      Old QB45 Programmer

                                      Comment


                                      • #20
                                        the method i suggested using a lengthy string, then rounding up to the decimal from right to left did not produce no better results that using the compiler built in round statment.
                                        rethinking
                                        paul
                                        p purvis

                                        Comment

                                        Working...
                                        X