Diving by zero in java

Java has some unusual and often unexpected results when dividing by zero when using variables of type int or double.

If you try and divide where both variables are of the type int, a “/ by zero” exception will be thrown.

If, however, you make one of the operands a double, no exception is thrown, and the operation completes successfully. It is important that at least one of the operands and not just the answer is of type double for the statement to complete so the operation itself is done with doubles. If you print the answer, the text “infinity” or “-infinity” will be output.

Why does this happen?

In short, ints have no value for infinity or values that aren’t a number. This means that when 2 ints are divided by zero, the result will always be an exception as the data type has no way to represent the result. Doubles on the other hand are floating point numbers, and floating point numbers can represent infinity or results that aren’t numbers so an operation like dividing by zero is completely valid.

In the examples below, you can see that by making just one of the operands a double, no runtime exception is thrown when dividing by zero and the value of the result is “infinity”. The same operations with ints simply throw an exception.


//Example of standard division of positive ints. 
//output= 4
<%
int aa = 12;
int bb = 3; 
int answer;
try {
answer = aa/bb;
out.println(answer);
} catch (Exception e) {
	out.println("I am a runtime exception!");
}

//Example of dividing by zero using ints.
//output = exception. Exception message: / by zero
int a2 = 12;
int b2 = 0; 
int answer2;
try {
answer2 = a2/b2;
out.println(answer2);
} catch (Exception e) {
	out.println("I am a runtime exception. Exception message: " + e.getMessage());
}

//Example of an int divided by a double. As one of the operands is a double, the answer to will be a double. This works and the answer comes out to be NaN (Not a Number). See the output of 'Infinity' from the below code. 
//output = Infinity 
int a3 = 12;
double b3 = 0; //one of the divisors needs to be a double to work. 
double answer3;
try {
answer3 = a3/b3;
out.println(answer3);
} catch (Exception e) {
	out.println("I am a runtime exception. Exeption message: " + e.getMessage());
}

//Example of int divided by an int.
//output = I am a runtime exception. Exception message: / by zero
int a4 = 12;
int b4 = 0; //one of the divisors needs to be a double to work. 
double answer4;
try {
answer4 = a4/b4;
out.println(answer4);
} catch (Exception e) {
	out.println("I am a runtime exception. Exception message: " + e.getMessage());
}

Exception hanlding and logging of pl/SQL

pl/SQL Logging
During a batch process or the execution of pl/SQL, you will want to log the output and the success or failure of the process.

Typically, I always find it good practice to output some simple information such as the start and end date/time of the process as well as any errors that may occur. This is really handy if you are wanting to look at how long a process takes and will give you a feel for if something ‘went wrong’ while running the script.

If you run a script as a one off, you will see the output of your code (package, procedure, anonomous block) in the output from your IDE such as TOAD, SQL developer or SQL*Plus.

Example:

set serveroutput on

... your code

or you can redirect it to a file (see below)

Example:

set serveroutput on
spool log.txt

... your code

spool off

If you run a batch process using crontab or some other scheduler, use this to redirect your output into a file. If you do this, it is always a good idea to time stamp the file.

Exception handling
In your batch pl/SQL applications, you will need to have some exception handling.

If anything, you will want to catch some specific errors as well as others.

In my examples below, I am catching a NO_DATA_FOUND exception and outputting a different error to when any other exception occurs.

Example:

BEGIN 

	DBMS_OUTPUT.PUT_LINE('Batch process started - '||SYSDATE);
	
	... your pl/SQL block that does stuff...

	COMMIT; --commit changes 
	DBMS_OUTPUT.PUT_LINE('Batch process ended - '||SYSDATE);
	
EXCEPTION
   WHEN NO_DATA_FOUND THEN
      ROLLBACK;
	  
      DBMS_OUTPUT.PUT_LINE('No data was found - '||SQLCODE||' -ERROR- '||SQLERRM);

EXCEPTION
   WHEN OTHERS THEN
	  ROLLBACK;
      DBMS_OUTPUT.PUT_LINE('An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;

Raising your own exceptions
Another option is when you come across a condition in your code where you want to throw an exception. A really good example of this is if a variable ends up with a negative number you may want to raise an exception rather than let the program continue on.

Example:

BEGIN

	IF input > 0 THEN
		... your pl/SQL block that does stuff...
	ELSIF input = -1
		--Raise no data found exception if 
		RAISE NO_DATA_FOUND; 
	
	ELSE
		--Something wrong has happened. Raise an exception. 
		RAISE;
	END IF:

	EXCEPTION
	   WHEN NO_DATA_FOUND THEN
		  DBMS_OUTPUT.PUT_LINE('Please enter a correct paramater and try again.');

	EXCEPTION
	   WHEN OTHERS THEN
		  DBMS_OUTPUT.PUT_LINE('An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
	END;
END;

Creating your own custom exceptions
It is also possible to create your own exceptions and even allocate them to their own error number within the user-specified range of between -20000 – -20999. All other error numbers are reallocated to standard oracle errors. While this is certainly possible, I’ve never found a real life scenario where I have wanted to create my own exceptions as the Oracle keywords and mapping to error numbers have been sufficient for most needs. (hence why I haven’t included an example)