\(E'(5.5) = \frac{E(5.5+\epsilon_c) - E(5.5)}{\epsilon_c} \)
\(\epsilon_c = (1より大きい最小の値) - 1 \)
⇒ 要は仮数部で表すことができる最も小さい数\(\epsilon_c = \\ ~~2^0 \times (1.00000000000000000000001_{(2)})\\ - 2^0 \times (1.00000000000000000000000_{(2)})\\ = 2^0 \times (0.00000000000000000000001_{(2)}) = 2^{-23} \)
\(\epsilon_c = \\ ~~2^0 \times (1.0000000000000000000000000000000000000000000000000001_{(2)})\\ - 2^0 \times (1.0000000000000000000000000000000000000000000000000000_{(2)})\\ = 2^0 \times (0.0000000000000000000000000000000000000000000000000001_{(2)}) = 2^{-52} \)
C では、浮動小数点型変数のポインタからメモリの内容を取得したり、Union で同じメモリ領域を指す float と int を作ったりしたけど、Java ではどうすんだろ? ⇒ Float クラスに内部表記を取り出すための API がある
package com.mycompany.sandbox; public class FloatExam { public static void main(String[] args) { System.out.println(floatExpression(2.5f)); System.out.println(floatExpression(-2.5f)); System.out.println(floatExpression(1.0f)); System.out.println(floatExpression(0.1f)); // 1 より大きい最小の数 float ce = ieee2float(0, 127, 1); System.out.println("1.0+ε = " + floatExpression(ce)); // 計算機イプシロン System.out.println(" ε = " + floatExpression(ce - 1.0f)); } private static String floatExpression(final float f) { int i = Float.floatToIntBits(f); StringBuilder sb = new StringBuilder(); int sign = subint(i, 31, 31); int exponent = subint(i, 30, 23); int fraction = subint(i, 22, 0); sb .append(f).append(" = ") .append(0 == sign ? "+1" : "-1") .append(" * 2^(").append(exponent).append("-127)") .append(" * ").append(1.0F + fraction * Math.pow(2.0, -23)) .append("\n"); sb .append(sign).append(" ") .append(int2bin(exponent, 8)).append(" ") .append(int2bin(fraction, 23)).append("\n"); return sb.toString(); } private static float ieee2float(final int sign, final int exponent, final int fraction) { double f = (0 == sign ? +1.0 : -1.0) * Math.pow(2.0, exponent - 127) * (1.0 + fraction * Math.pow(2.0, -23)); return (float) f; } private static int subint(final int i, final int from, final int to) { return (i << (31 - from) >>> (31 - from + to)); } private static String int2bin(final int i, final int size) { StringBuilder sb = new StringBuilder(); sb.append(Integer.toString(i, 2)); while (sb.length() < size) { sb.insert(0, "0"); } return sb.toString(); } }
2.5 = +1 * 2^(128-127) * 1.25 0 10000000 01000000000000000000000 -2.5 = -1 * 2^(128-127) * 1.25 1 10000000 01000000000000000000000 1.0 = +1 * 2^(127-127) * 1.0 0 01111111 00000000000000000000000 0.1 = +1 * 2^(123-127) * 1.600000023841858 0 01111011 10011001100110011001101 1.0+ε = 1.0000001 = +1 * 2^(127-127) * 1.0000001192092896 0 01111111 00000000000000000000001 ε = 1.1920929E-7 = +1 * 2^(104-127) * 1.0 0 01101000 00000000000000000000000