Announcement

Collapse
No announcement yet.

Why is A\B <> fix(A/B) ?

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

  • Why is A\B <> fix(A/B) ?

    Code:
        local A&, B%
        local BSlashQuotient, FixQuotient as integer
    
        A& = 400000
        B% = 6
    
        BSlashQuotient = A& \ B%
        FixQuotient    = fix (A& / B%)
        ? A& B% BSlashQuotient FixQuotient
    The output of the above code is:
    400000 6 1130 -32768

    using long quotients, the output is:
    400000 6 66666 66666

    With integer quotients, when overflow occurs:
    fix (A/B) always = -32768
    A\B always = the correct integer quotient - 65,536.

    Does anyone know why?

    And, is there any way to generate a run-time warning when overflow occurs?

  • #2
    FixQuotient = fix (A& / B%)
    Use FixQuotient = cint(fix (A& / B%))
    Forum: http://www.jose.it-berater.org/smfforum/index.php

    Comment


    • #3
      Originally posted by José Roca View Post
      Use FixQuotient = cint(fix (A& / B%))
      Huh???

      Code:
      local A&, B%
       local BSlashQuotient, FixQuotient, JoseQuotient as long
      
       A& = 400000
       B% = 6
      
       BSlashQuotient = A& \ B%
       FixQuotient    = fix (A& / B%)
       JoseQuotient  = cint(fix (A&/B%))
       ? A& B% BSlashQuotient FixQuotient JoseQuotient
      Output:
      400000 6 66666 66666 1130

      With:
      Code:
      local BSlashQuotient, FixQuotient, JoseQuotient as integer
      Output is:
      400000 6 1130 -32768 1130

      Comment


      • #4
        The "problem" with cint was caused by fact the 66 666 (quite hellish choice) is bigger than 32 767 ( integer in PB is 16 bit).

        As the result falls in long integer (32 bit) range, you can simply use:
        FixQuotient = cLng(fix (A& / B%))
        The root of the problem is in fact you originally assigned number bigger than 16bit integer range to 16bit integer variable.
        If you know the numbers will fall outside integer number, please use longs. They are still small in memory, they are very efficientely handled by compiler, and you can even register them on the CPU. Ideal
        Last edited by Petr Schreiber jr; 19 Oct 2009, 07:50 AM.
        [email protected]

        Comment


        • #5
          Huh???
          CINT is for integers. There is a function for each type:

          Code:
          bytevar?          = CBYT(numeric_expression)
          [email protected]      = CCUR(numeric_expression)
          [email protected]@  = CCUX(numeric_expression)
          doublevar#        = CDBL(numeric_expression)
          doublewordvar???  = CDWD(numeric_expression)
          extendedvar##     = CEXT(numeric_expression)
          integervar%       = CINT(numeric_expression)
          longintvar&       = CLNG(numeric_expression)
          quadintvar&&      = CQUD(numeric_expression)
          singlevar!        = CSNG(numeric_expression)
          wordvar??         = CWRD(numeric_expression)
          Forum: http://www.jose.it-berater.org/smfforum/index.php

          Comment


          • #6
            66666 - 1130 = 65536 i.e. 2^16
            It would appear the BSlashQuotient is being calculated using longs math so no overflow but then taking the low order byte as the result because the result type is an integer thus the 17th bit is being lost.

            Comment


            • #7
              Code:
              local A&, [COLOR="Red"]B%[/COLOR]
              local BSlashQuotient, FixQuotient [COLOR="Red"]as integer[/COLOR]
              You can't put a quart in a pint pot.

              'Size of result' aside, with the 32-bit compilers just make all your integer class variables LONG unless A) you need something larger or B) there is a really compelling reason to use something smaller. The compiler eats LONG integers for breakfast.
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                Thanks for the replies guys. As indicated in the original question, I realised that if you try to pour a quart of water into a pint pot it's going to overflow, and that with longs there is no overflow with the values used here.

                Originally, the purpose of the experiment was to test a vague recollection (which turned out to be wrong) that Q = A\B would only return an integer-sized result even when the true result and the variable it was assigned to were both longs.

                What I was trying to understand here was why, when overflow occurs, A\B produces a different result from fix(A/B), when both, ostensibly, do the same thing. John's reply (#6) seems to shed some light on this.

                Actually, come to think of it, the difference between the two in the way they do the maths could be useful as a crude run-time test for overflow (at least specifically for this type of integer division). Whenever the two results differ, you know overflow has occurred. The test fails for the border-conditions where both produce the result -32,768 (e.g. 196612 \ 6).

                Comment


                • #9
                  The result of an invalid operation is undefined. I hope that is clear? You should not rely on it.

                  Comment


                  • #10
                    Code:
                    #DEBUG OVERFLOW ON    ' sets error 6 "overflow"
                    Oops, my bad. That NFS has not yet been implemented.
                    Michael Mattias
                    Tal Systems (retired)
                    Port Washington WI USA
                    [email protected]
                    http://www.talsystems.com

                    Comment


                    • #11
                      To add to Tom's reply it is almost documented. To explain a&\b% will be performed between two longs as there is a long specified in the calculation so no overflow. The result is specified to be an integer so in line with the basic concept of Basic a conversion will be automatically done, I expect with the equivalent of a MAK or LO instruction thus dropping the 17th bit.

                      Comment


                      • #12
                        According to the PB documentation CINT and INT will do rounding while FIX simply drops any fractions and returns the integer digits. I'm not sure if doing an integer division (using the \ operator) will also do rounding but if it does, then A\B will not always be equal to FIX(A\B).
                        Jeff Blakeney

                        Comment


                        • #13
                          "\" stipulates an integer division. There is no floating point, so there is no rounding to be done.

                          Comment


                          • #14
                            COBOL:
                            Code:
                             WORKING STORAGE SECTION. 
                               77  A    PICTURE  S9(9) USAGE BINARY.     << as close as you can get to a BASIC LONG integer
                               77  B    PICTURE  S9(9) USAGE BINARY. 
                               77  C    PICTURE  S9(9) USAGE BINARY. 
                               77  A    PICTURE  S9(9) USAGE BINARY. 
                            
                            .....
                            DIVIDE
                               A INTO B 
                                 GIVING  C 
                                   REMAINDER  D 
                            END-DIVIDE
                            BASIC
                            Code:
                             LOCAL A, B, C, D AS LONG
                            
                             C =  B\A
                             D  = B MOD A
                            COBOL
                            Code:
                             [SAME W-S]
                            DIVIDE  
                               A INTO B 
                                   GIVING  C  [b][COLOR="Red"]ROUNDED[/COLOR][/b] 
                                      REMAINDER  D 
                            END-DIVIDE
                            BASIC:
                            Code:
                              C =  B/A 
                              D =  B MOD A
                            MCM
                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                            • #15
                              Originally posted by Tom Hanlin View Post
                              The result of an invalid operation is undefined. I hope that is clear? You should not rely on it.
                              What's invalid about Q = A\B or Q = fix(A/B)? They are valid statements. It is the values thrown at them that cause the overflow condition, which is not always predictable. (The program may be using values input by a user.) Since PB programs no longer generate run-time errors in case of overflow, surely the compiler should at least deal with overflow in a predictable manner?

                              Comment


                              • #16
                                > surely the compiler should at least deal with overflow in a predictable manner?

                                Send in a new feature suggestion for #DEBUG OVERFLOW ON. You should get the coveted "checkmark" since I asked for that literally years ago.

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

                                Comment


                                • #17
                                  Originally posted by Jeff Blakeney View Post
                                  ... FIX simply drops any fractions and returns the integer digits. I'm not sure if ... A\B will ... always be equal to FIX(A\B).
                                  The original subject line may have been slightly misleading. A\B returns the same result as fix(A/B) except when overflow occurs.

                                  ADDENDUM:

                                  Whoops, just noticed your typo Jeff. Just to be absolutely clear: you wrote "FIX(A\B)" which is EXACTLY the same as A\B except that the FIX() portion is entirely redundant. I'm sure you meant to write "FIX(A/B)", which is what I was comparing/contrasting with A\B.
                                  Last edited by Mottel Gutnick; 20 Oct 2009, 06:23 PM. Reason: Addendum added

                                  Comment


                                  • #18
                                    Originally posted by Michael Mattias View Post
                                    Send in a new feature suggestion ...
                                    MCM
                                    Is there an area in the forums for putting in such requests or do you email them directly to support?

                                    ADDENDUM:
                                    Er, belay that request Scottie ... just found the link to the Feature Request Webpage in a sticky post on another forum.
                                    Last edited by Mottel Gutnick; 20 Oct 2009, 07:29 PM. Reason: Addendum

                                    Comment


                                    • #19
                                      "On two occasions, I have been asked , "Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?" I am not able to rightly apprehend the kind of confusion of ideas that could provoke such a question." - Charles Babbage

                                      Yes, overflow detection would be a great feature. Yes, it's on the list. No, you may not expect the compiler to produce predictable results when you give it data that doesn't fit into the buckets you specified.

                                      Comment


                                      • #20
                                        Originally posted by Tom Hanlin View Post
                                        "\" stipulates an integer division. There is no floating point, so there is no rounding to be done.
                                        Division of any kind can result in a floating point number and therefore rounding can be performed. I just ran this like test program:

                                        Code:
                                        FUNCTION PBMAIN () AS LONG
                                        
                                            MSGBOX "9 / 10 = "     + FORMAT$(9/10)       + $CRLF + _
                                                   "9 \ 10 = "     + FORMAT$(9\10)       + $CRLF + _
                                                   "FIX(9/10) = "  + FORMAT$(FIX(9/10))  + $CRLF + _
                                                   "INT(9/10) = "  + FORMAT$(INT(9/10))  + $CRLF + _
                                                   "CINT(9/10) = " + FORMAT$(CINT(9/10)) + $CRLF + _
                                                   "CEIL(9/10) = " + FORMAT$(CEIL(9/10))
                                        
                                        END FUNCTION
                                        Not all the result are what I was initially expecting. I got the following results:

                                        9 / 10 = .9
                                        9 \ 10 = 0
                                        FIX(9/10) = 0
                                        INT(9/10) = 0
                                        CINT(9/10) = 1
                                        CEIL(9/10) = 1
                                        I'm pretty sure it was Bob Zale that said in another thread that PB follows the IEEE standard for rounding and I think there might be some confusion about the usage of the term rounding in the documentation. The documentation for the FIX statement says that it doesn't do any rounding, which is shown with these results, but it also says that INT and CINT do perform rounding but the results show that CINT does but INT doesn't. Looking at the documentation for INT, CINT and CEIL it seems that the "rounding" these functions are doing is simply to drop any fractional results (INT) or go to the next higher integer if there are fractional results (CINT and CEIL).

                                        Perhaps the confusion is on my part because when I think of rounding I think of the scientific rounding that I was taught in school where 1.1 becomes 1, 1.5 becomes 2, 1.9 becomes 2, 2.1 becomes 2, 2.5 becomes 2 and 2.9 becomes 3. I don't know what the IEEE standard Bob mentioned is or how it works.

                                        What it boils down to in PB is that integer division (using the \ operator), FIX and INT will all give the same results by dropping any fractional result and CINT and CEIL will give a different result by incrementing the integer portion by one if the fractional portion is not zero.

                                        Mottel, you were right, FIX(A\B) was a typo on my part and should have been FIX(A/B).
                                        Jeff Blakeney

                                        Comment

                                        Working...
                                        X