Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching exception: divide by zero

The following code does not catch an exception, when I try to divide by 0. Do I need to throw an exception, or does the computer automatically throw one at runtime?

int i = 0;  cin >> i;  // what if someone enters zero?  try {     i = 5/i; } catch (std::logic_error e) {      cerr << e.what(); } 
like image 524
user33424 Avatar asked May 25 '11 08:05

user33424


People also ask

What kind of exception is divide by 0?

Hence, if any number is divided by zero, we get the arithmetic exception .

Does dividing by 0 cause a runtime error?

Definition. Division by zero is a logic software bug that in most cases causes a run-time error when a number is divided by zero.

Is division by 0 allowed in Java?

Values like INFINITY and NaN are available for floating-point numbers but not for integers. As a result, dividing an integer by zero will result in an exception. However, for a float or double, Java allows the operation. The complete code is available over on GitHub.

How do you handle zero division exception in Java?

Java will not throw an exception if you divide by float zero. It will detect a run-time error only if you divide by integer zero not double zero. If you divide by 0.0, the result will be INFINITY.


2 Answers

You need to check it yourself and throw an exception. Integer divide by zero is not an exception in standard C++.

Neither is floating point divide by zero but at least that has specific means for dealing with it.

The exceptions listed in the ISO standard are:

namespace std {     class logic_error;         class domain_error;         class invalid_argument;         class length_error;         class out_of_range;     class runtime_error;         class range_error;         class overflow_error;         class underflow_error; } 

and you could argue quite cogently that either overflow_error (the infinity generated by IEEE754 floating point could be considered overflow) or domain_error (it is a problem with the input value) would be ideal for indicating a divide by zero.

However, section 5.6 (of C++11, though I don't think this has changed from the previous iteration) specifically states:

If the second operand of / or % is zero, the behavior is undefined.

So, it could throw those (or any other) exceptions. It could also format your hard disk and laugh derisively :-)


If you wanted to implement such a beast, you could use something like intDivEx in the following program (using the overflow variant):

#include <iostream> #include <stdexcept>  // Integer division/remainder, catching divide by zero.  inline int intDivEx (int numerator, int denominator) {     if (denominator == 0)         throw std::overflow_error("Divide by zero exception");     return numerator / denominator; }  inline int intModEx (int numerator, int denominator) {     if (denominator == 0)         throw std::overflow_error("Divide by zero exception");     return numerator % denominator; }  int main (void) {     int i = 42;      try { i = intDivEx (10, 0); }     catch (std::overflow_error &e) {         std::cout << e.what() << " -> ";     }     std::cout << i << std::endl;      try { i = intDivEx (10, 2); }     catch (std::overflow_error &e) {         std::cout << e.what() << " -> ";     }     std::cout << i << std::endl;      return 0; } 

This outputs:

Divide by zero exception -> 42 5 

and you can see it throws and catches the exception (leaving the return variable untouched) for the divide by zero case.


The % equivalent is almost exactly the same:

like image 94
paxdiablo Avatar answered Sep 21 '22 22:09

paxdiablo


Updated with comments from ExcessPhase

GCC (at least version 4.8) will let you emulate this behaviour:

#include <signal.h> #include <memory> #include <iostream>  int main() {     std::shared_ptr<void(int)> handler(         signal(SIGFPE, [](int signum) {throw std::logic_error("FPE"); }),         [](__sighandler_t f) { signal(SIGFPE, f); });      int i = 0;      std::cin >> i;  // what if someone enters zero?      try {         i = 5/i;     }     catch (std::logic_error e) {         std::cerr << e.what();     } } 

This sets up a new signal handler which throws an exception, and a shared_ptr to the old signal handler, with a custom 'deletion' function that restores the old handler when it goes out of scope.

You need to compile with at least these options:

g++ -c Foo.cc -o Foo.o -fnon-call-exceptions -std=c++11 

Visual C++ will also let you do something similar:

#include <eh.h> #include <memory>  int main() {     std::shared_ptr<void(unsigned, EXCEPTION_POINTERS*)> handler(         _set_se_translator([](unsigned u, EXCEPTION_POINTERS* p) {             switch(u) {                 case FLT_DIVIDE_BY_ZERO:                 case INT_DIVIDE_BY_ZERO:                     throw std::logic_error("Divide by zero");                     break;                 ...                 default:                     throw std::logic_error("SEH exception");             }         }),         [](_se_translator_function f) { _set_se_translator(f); });      int i = 0;      try {         i = 5 / i;     } catch(std::logic_error e) {         std::cerr << e.what();     } } 

And of course you can skip all the C++11-ishness of this and put them in a traditional RAII-managing struct.

like image 24
Tom Avatar answered Sep 22 '22 22:09

Tom