0*Infinity==NaN; 1/-Infinity==-0

The Java floating-point types have special values for negative zero, positive and negative infinity, and not-a-number, or NaN. I hacked up a short program (below) to print out a multiplication table for these special values, and also tables for the +, -, /, and % operators as well. For the most part, these special values behave as you'd expect when you do arithmetic with them. But some of the values produce results that may seem suprising. 1/0 produces infinity, of course, but 0/0 produces NaN which may not be obvious at first. (If you divide by zero using an integer type instead of a floating point type, you get an ArithmeticException. Floating-point arithmetic never throws exceptions in Java.)

The code is below. Cut, paste, compile and run..

public class Arithmetic {
    static final double negzero = 1/Double.NEGATIVE_INFINITY;

    static double[] operands = new double[] {
	0.0, negzero, 1.0,
	Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NaN
    };

    // Print a double value as a string.  Java would do this conversion 
    // for us, but we want "Inf" instead of "Infinity", which is too
    // wide for tab-separated tables.
    static void print(double x) {
	if (Double.isNaN(x)) System.out.print("NaN\t");
	else if (Double.isInfinite(x)) {
	    if (x < 0) System.out.print("-");
	    System.out.print("Inf\t");  // "Infinity" is too long
	}
	else if (x == 0) {
	    if (1/x == Double.NEGATIVE_INFINITY) System.out.print("-");
	    System.out.print("0.0\t");
	}
	else System.out.print(x + "\t");
    }


    // Print the header row for each table
    static void printHeader(String operator) {
	System.out.println();
	System.out.print(operator + "\t");
	for(int col = 0; col < operands.length; col++) print(operands[col]);
	System.out.println();
    }

    // print out all the tables.
    public static void main(String[] args) {
	printHeader("+");
	for(int row = 0; row < operands.length; row++) {
	    print(operands[row]);
	    for(int col = 0; col < operands.length; col++) 
		print(operands[row] + operands[col]);
	    System.out.println();
	}


	printHeader("-");
	for(int row = 0; row < operands.length; row++) {
	    print(operands[row]);
	    for(int col = 0; col < operands.length; col++) 
		print(operands[row] - operands[col]);
	    System.out.println();
	}

	printHeader("*");
	for(int row = 0; row < operands.length; row++) {
	    print(operands[row]);
	    for(int col = 0; col < operands.length; col++) 
		print(operands[row] * operands[col]);
	    System.out.println();
	}

	printHeader("/");
	for(int row = 0; row < operands.length; row++) {
	    print(operands[row]);
	    for(int col = 0; col < operands.length; col++) 
		print(operands[row] / operands[col]);
	    System.out.println();
	}

	printHeader("%");
	for(int row = 0; row < operands.length; row++) {
	    print(operands[row]);
	    for(int col = 0; col < operands.length; col++) 
		print(operands[row] % operands[col]);
	    System.out.println();
	}
    }
}

Books

Comprehensive coverage of Ruby 1.8 and 1.9

"The New Most Important Ruby Book"
Peter Cooper,
rubyinside.com

Completely updated for Ajax and Web 2.0

"A must-have reference"
Brendan Eich,
creator of JavaScript

The classic Java quick-reference