No announcement yet.

Strange Div By Zero Behavior

  • Filter
  • Time
  • Show
Clear All
new posts

  • Strange Div By Zero Behavior

    I have found a behaviour wich drove me crazy.

    x = 0
    y = x / 0 'this works
    MSGBOX STR$(y)
    y = x \ 0 'this causes a GPF
    MSGBOX STR$(y)

    is there any compiler switch or assembler code witch turns
    of the checking for div by zero?


  • #2
    Intercepting Division by Zero (and other numeric over/underflows) are the responsibility of the programmer.

    Please review the "Errors and Error Testing" chapter in the documentation for more information.

    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    mailto:[email protected]


    • #3
      Lance, thx for the answer, but you have
      only answered on question.
      Why does a floating division by zero works, but
      not an integer division? At least with PBDLL60.

      I know the windows structured error handling.
      It seems to be the only way?


      [This message has been edited by Torte Torsten (edited July 07, 2001).]


      • #4
        Guess, that PB uses DIV/IDIV for integer division and co-processor commands (something, like FDIV) for / (even if both operands are integer)
        According my assembler book, DIV & IDIV generate exception (\), if to divide on 0.
        About FDIV - no one word about exception.

        E-MAIL: [email protected]


        • #5
          Why does a floating division by zero works, but
          not an integer division? At least with PBDLL60.
          Floating division by zero NEVER works. Of course, neither does integer division by zero.

          Maybe one causes an immediate GPF and one doesn't, but neither "works" in the sense that get an answer.


          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]


          • #6
            One possible explaination is one I ran across a number of years
            ago. The short answer is "a zero is not necessairly a zero".

            If you have a division where the apparent result is zero, the
            actual value may be carried out to several decimal places. For

            "##" would give a formatted value of "00" but
            "##########" would show "0000000012" giving a value of <> zero.

            This may be an explaination or not.

            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.


            • #7
              Intercepting Division by Zero (and other numeric over/underflows) are the responsibility of the programmer.
              Lance, I don't see where/how PowerBASIC gives the programmer any means of detecting floating point divide by zero (and other fp) errors.
              FP exceptions are disabled by default and there is no means of enabling these from PowerBASIC.

              If I am wrong, please show me the way.


              • #8
                OK, (quoting Matt Pietrek) "Win32 initializes the floating point unit to not generate exceptions".

                To enable floating point exceptions you need to mangle some bits in the coprocessor's control word.
                Here's the code to do that:
                !fninit               ' Initialize the coprocessor
                !fstcw cw
                cw = cw And &hFFE0    ' Turn off the most of the exception bits (except the precision exception)
                !fldcw cw
                Use this with Florent's SEH code and you can trap the floating point exceptions along with the others.
                (Thanks again, Florent!)



                • #9
                  Folks, trapping a division by zero is hardly difficult... if there any possibility that the denominator is zero, just test for such a case before doing the calculation.

                  As Michael stated, division by zero in any form cannot be evaluated.

                  PowerBASIC Support
                  mailto:[email protected][email protected]</A>
                  mailto:[email protected]


                  • #10
                    From the Intel manual,


                    If an unmasked divide by zero exception (#Z) is generated, no result is stored; if the exception
                    is masked, an ¥ of the appropriate sign is stored in the destination operand.

                    ¥ = infinity sign


                    [email protected]

                    hutch at movsd dot com
                    The MASM Forum - SLL Modules and PB Libraries



                    • #11
                      A while ago our app crashed a lot on specific computers.
                      Armada 100's
                      It seemed the cpu was very easily to crash.
                      The VB3 divison by zero was also one of it's problems.
                      Now we test the variable before division, else we skip the divison.




                      • #12
                        I successful received FPU exception on my PC (P3, Win2000).
                        Of course, I changed default swr.
                        What's interesting 0 / 0 - is "invalid operation", 10 / 0 - "division by 0"
                           #Compile Exe
                           #Dim All
                           #Register None
                           #Include "WIN32API.INC"
                           Type EXCEPTION1_POINTERS ' <--- Because of mistake in Win32Api.Inc
                              pExceptionRecord As EXCEPTION_RECORD Ptr
                              pContextRecord As CONTEXT Ptr
                           End Type
                           Global Stmt As Long
                           Function OurUnhandledExceptionFilter(Exception_Pointers As EXCEPTION1_POINTERS) As Long
                              Dim Msg As String
                              Select Case [email protected]
                                 Case %EXCEPTION_FLT_DENORMAL_OPERAND  : Msg = "Float denormal operand"
                                 Case %EXCEPTION_FLT_DIVIDE_BY_ZERO    : Msg = "Float divide by zero"
                                 Case %EXCEPTION_FLT_INEXACT_RESULT    : Msg = "Float inexact result"
                                 Case %EXCEPTION_FLT_INVALID_OPERATION : Msg = "Float invalid operation"
                                 Case %EXCEPTION_FLT_OVERFLOW          : Msg = "Float overflow"
                                 Case %EXCEPTION_FLT_STACK_CHECK       : Msg = "Float stack check"
                                 Case %EXCEPTION_FLT_UNDERFLOW         : Msg = "Float underflow"
                                 Case %EXCEPTION_ACCESS_VIOLATION      : Msg = "Access violation"
                                 Case %EXCEPTION_INT_DIVIDE_BY_ZERO    : Msg = "Integer divide by zero"
                                 Case %EXCEPTION_INT_OVERFLOW          : Msg = "Integer Overflow"
                                 Case Else                             : Msg = "Exception &H" + Hex$([email protected])
                              End Select
                              ! FINIT   ' <-- May be I lost something from float exceptions; so better to reset anyway
                              MsgBox Msg + " at statement" + Str$(Stmt), %MB_TASKMODAL, "Program Error"
                              Function = %EXCEPTION_EXECUTE_HANDLER ' %Exception_Continue_Execution
                            End Function
                            Function PbMain() As Long
                               Dim x As Integer, y As Integer
                               SetUnhandledExceptionFilter ByVal CodePtr(OurUnhandledExceptionFilter)
                               ' Test for access violation
                               ' Dim b As Byte Ptr: Stmt = 1: @b = 0       
                               ! FSTCW x
                               x = x And &HFF30
                               ! FLDCW x  ' <-- Allow FPU exceptions
                               Stmt = 14: x = 0: x = x / y ' <-- Float invalid operation
                               ' If to comment x = x / y then
                               Stmt = 15: x = 10: x = x / y  ' <--- Float divide by zero
                               MsgBox "Finished" ' <-- Doesn't work, because we already exited
                            End Function
                        E-MAIL: [email protected]


                        • #13
                          Thanks to all for the discussion of this topic.



                          • #14
                            I have several comments. First, I assumed that although PB did
                            not do numeric error handling, that for something like division
                            by 0 it would simply return an invalid number, but you'd only
                            have to worry about the wrong result, and not a GPF.

                            Secondly, perhaps I'm overlooking something very obvious. If
                            preventing a division by 0 in a calculation is always fast and
                            straight-forward, please show me how to do it for instance with
                            the following simple line of code:

                            Result = 1/(1/sin(a)+1/cos(b))

                            What can I do to ensure that a division by 0 does not occur here?
                            (without incurring a major speed penalty)

                            And then thirdly, although division by 0 is undefined mathematically,
                            on today's chips with only finite floating point ability, for
                            practical purposes division by 0 is in fact evaluated. A positive
                            number divided by 0 evaluates to positive infinity (defined on the
                            chip as the maximum floating point number); a negative number / 0
                            is negative infinity. 0/0 is not represented as a floating point,
                            but as a special value NaN (Not a Number). (And to get more
                            technical, there's even positive and negative 0, etc...). This is
                            not something peculiar to Intel chips. It's part of the IEEE 754
                            (or 854) standard which is widely implemented by chip makers.

                            Although it may not be necessary for the average programmer to
                            worry about such details, division by 0 does need to be handled
                            at one level or another. One option is to write programs
                            where 0 couldn't possibly end up as the denominator (this would
                            generally exclude scientific type apps), or the programmer can
                            add lines of code to prevent division by 0 from happening
                            (with a potential speed penalty), or you can just write a
                            program and not worry about it, and just hope that every thing
                            would be OK. But the programmer shouldn't be restricted to these
                            options, when chip makers and others have already gone to great
                            lengths to develop efficient ways of handling such exceptions.

                            (In my own math parser, division by 0 is intercepted just before
                            a division takes place, so there's no problem there. The user
                            can trap it with ucError).

                            Daniel Corbier
                            UCalc Fast Math Parser
                            Daniel Corbier
                            uCalc Fast Math Parser
                            uCalc Language Builder