\(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