// File Numbers.java for lecture on computer numbers // Contents: // * Binary representation of integers and floating-point numbers // * Experiments with IEEE 754-2008 floating point numbers: // infinities, NaNs, denormal numbers, etc. // * Examples of accurate and inaccurate numeric algorithms // * LaTeX code generator for tables of IEEE floating-point operations // Peter Sestoft * sestoft@itu.dk * 2009-02-15, 2011-10-28, 2012-02-08 class Numbers { public static void main(String[] args) { byteExamples(); intExamples(); floatExamples(); doubleExamples(); // Works only because IEEE handles infinities correctly: System.out.println("R(1) = " + R(1)); System.out.println("R(2) = " + R(2)); System.out.println("R(3) = " + R(3)); System.out.println("R(4) = " + R(4)); // Negative and positive zero double zp = 0.0, zn = -0.0; System.out.println(zp == zn && 1/zp != 1/zn); // true System.out.println((new Double(zp)).hashCode() + " " + (new Double(zn)).hashCode()); System.out.println(-0.0 < 0.0); // false allDoubleOperations(); Point[] ps1 = new Point[] { new Point(2.1, 5.2), new Point(2.2, 5.4), new Point(2.4, 5.8) }; linear1(ps1); linear2(ps1); Point[] ps2 = Point.moveAll(ps1, 1E7, 1E7); linear1(ps2); linear2(ps2); Point[] ps3 = Point.moveAll(ps1, 5E7, 5E7); linear1(ps3); linear2(ps3); // Testing sum final int N = 10000; final double[] xs = new double[2*N]; for (int i=0; i 0 ? (-b - y)/(2 * a) : (-b + y)/(2 * a); double x2 = c / (x1 * a); System.out.printf("Two solutions: %g and %g%n", x1, x2); } } // ------------------------------------------------------------ public static void denormalFloat() { float y = (float)Math.pow(2,-126); float d = y/4.0f; float x = y+d; displayFloat(x); displayFloat(y); displayFloat(x-y); } // ------------------------------------------------------------ public static void idempotence() { double z = Math.pow(2, 53); displayDouble(z); double zz = z+1; displayDouble(zz); System.out.println(z==zz); } // ------------------------------------------------------------ // Cancellation, loss of significant digits public static void cancellation() { double v = 9876543210.2, w = 9876543210.1; double r = v-w; // The actual representable doubles are // v~ = 9876543210.20000076293945312500 // w~ = 9876543210.10000038146972656250 // The difference between these is: // 0000000000.10000038146972656250 // So no surprise that the double result is // v-w = 0.10000038146972656000 System.out.printf("v = %.20f%n", v); displayDouble(v); System.out.printf("w = %.20f%n", w); displayDouble(w); System.out.printf("v-w = %.20f%n", r); displayDouble(r); displayExact("v = ", v); displayExact("w = ", w); displayExact("v-w = ", r); System.out.println(v+w-w != v); // true } // ------------------------------------------------------------ // Dangerous loops // This doesn't terminate! public static void oneTenth() { double d = 0.0; while (d != 1.0) { d += 0.1; System.out.printf("%.20f%n", d); } } // This does terminate! public static void wrapAround() { int i = 1; while (i>0) i++; System.out.print(i); } // ------------------------------------------------------------ // Linear regression computed two ways public static class Point { public final double x, y; public Point(double x, double y) { this.x = x; this.y = y; } public Point move(double dx, double dy) { return new Point(x + dx, y + dy); } public static Point[] moveAll(Point[] ps, double dx, double dy) { Point[] res = new Point[ps.length]; for (int i=0; i", new IFunction() { public String invoke(double x, double y) { return (x>y) + ""; }}); displayAll2(">=", new IFunction() { public String invoke(double x, double y) { return (x>=y) + ""; }}); System.out.println("\\subsection{Two-argument mathematical functions}"); displayAll2("Math.atan2", new IFunction() { public String invoke(double x, double y) { return String.format("%.3f", Math.atan2(x,y)); }}); displayAll2("Math.IEEEremainder", new IFunction() { public String invoke(double x, double y) { return Math.IEEEremainder(x,y)+""; }}); displayAll2("Math.max", new IFunction() { public String invoke(double x, double y) { return Math.max(x,y)+""; }}); displayAll2("Math.min", new IFunction() { public String invoke(double x, double y) { return Math.min(x,y)+""; }}); displayAll2("Math.pow", new IFunction() { public String invoke(double x, double y) { return Math.pow(x,y)+""; }}); System.out.println("\\subsection{One-argument mathematical functions}"); displayAll1( new Function1("Math.abs") { public double fun(double x) { return Math.abs(x); } }, new Function1("Math.acos") { public double fun(double x) { return Math.acos(x); } }, new Function1("Math.asin") { public double fun(double x) { return Math.asin(x); } }, new Function1("Math.atan") { public double fun(double x) { return Math.atan(x); } }, new Function1("Math.ceil") { public double fun(double x) { return Math.ceil(x); } }, new Function1("Math.cbrt") { public double fun(double x) { return Math.cbrt(x); } }, new Function1("Math.cos") { public double fun(double x) { return Math.cos(x); } }, new Function1("Math.exp") { public double fun(double x) { return Math.exp(x); } }, new Function1("Math.floor") { public double fun(double x) { return Math.floor(x); } }, new Function1("Math.log") { public double fun(double x) { return Math.log(x); } }, new Function1("Math.log10") { public double fun(double x) { return Math.log10(x); } }, new Function1("Math.rint") { public double fun(double x) { return Math.rint(x); } }, new Function1("Math.sin") { public double fun(double x) { return Math.sin(x); } }, new Function1("Math.signum") { public double fun(double x) { return Math.signum(x); } }, new Function1("Math.sqrt") { public double fun(double x) { return Math.sqrt(x); } }, new Function1("Math.tan") { public double fun(double x) { return Math.tan(x); } } ); } interface IFunction { public String invoke(double x, double y); } abstract static class Function1 { public final String name; public Function1(String name) { this.name = name; } public String invoke(double x) { return String.format("%.3f", fun(x)); } abstract public double fun(double x); } private final static double[] values = { Double.NEGATIVE_INFINITY, -2.0, -0.0, 0.0, +2.0, Double.POSITIVE_INFINITY, Double.NaN }; private static void displayAll2(String name, IFunction function) { System.out.println("\\noindent"); System.out.println("\\begin{tabular}{r|rrrrrrr}"); System.out.print("\\multicolumn{1}{c|}{" + name + "}"); for (int i=0; i