실수 2 개 사이의 모든 수는 셀 수 없다.
그러나, 컴퓨터의 2개의 float (부동소수점) 값 사이에는 개수는 정해져 있다.
java의 Math 클래스의 nextup 메소드를 이용하면 그 다음 float 값을 찾을 수 있다.
예제는 다음과 같다.
public static void main (String [] args) {
int number = 0;
for (float x = 1.0f; x <= 2.0f; x = Math.nextUp(x)) {
number++;
}
System.out.println("number : " + number);
}
결과는 8388609 이다.
인접하고 있는 float 숫자 사이에는 간격이 존재한다. 간격이 되는 값을 알아본다.
float next = Math.nextAfter(1.0f, 2.0f);
System.out.println("next : " + next);
실행하면, 1.0000001을 확인할 수 있다.
1.0f 부터 한 단계 큰 부동소수점 값은 1.0000001 이다. 0.0000001 값을 ulp (unit of least precision; 최종 자릿수)이라 한다.
ulp는 상대적인 값이다. float 값에 따라 0.0000002이 되기도 하고, 0.00006이 되기도 한다.
float next = Math.nextAfter(2.0f, 3.0f);
System.out.println("next : " + next + "\t" + Math.ulp(next)); // 결과 // next : 2.0000002 2.3841858E-7
float next = Math.nextAfter(1000.0f, 1100.0f);
System.out.println("next : " + next + "\t" + Math.ulp(next)); // 결과 // next : 1000.00006 6.1035156E-5
아래 코드를 실행해 본다.
int count = 0;
for (float x = 1.0f; x <= Float.MAX_VALUE ; x *= 2.0f) {
System.out.println (count++ + ": " + x + "\t\t"+ Math.getExponent(x) + "\t\t"+ Math.ulp (x));
}
결과
0: 1.0 0 1.1920929E-7
1: 2.0 1 2.3841858E-7
2: 4.0 2 4.7683716E-7
3: 8.0 3 9.536743E-7
4: 16.0 4 1.9073486E-6
5: 32.0 5 3.8146973E-6
6: 64.0 6 7.6293945E-6
7: 128.0 7 1.5258789E-5
8: 256.0 8 3.0517578E-5
9: 512.0 9 6.1035156E-5
10: 1024.0 10 1.2207031E-4
11: 2048.0 11 2.4414062E-4
12: 4096.0 12 4.8828125E-4
13: 8192.0 13 9.765625E-4
14: 16384.0 14 0.001953125
15: 32768.0 15 0.00390625
16: 65536.0 16 0.0078125
17: 131072.0 17 0.015625
18: 262144.0 18 0.03125
19: 524288.0 19 0.0625
20: 1048576.0 20 0.125
21: 2097152.0 21 0.25
22: 4194304.0 22 0.5
23: 8388608.0 23 1.0
24: 1.6777216E7 24 2.0
25: 3.3554432E7 25 4.0
26: 6.7108864E7 26 8.0
27: 1.34217728E8 27 16.0
28: 2.68435456E8 28 32.0
29: 5.3687091E8 29 64.0
30: 1.07374182E9 30 128.0
31: 2.14748365E9 31 256.0
32: 4.2949673E9 32 512.0
33: 8.5899346E9 33 1024.0
34: 1.71798692E10 34 2048.0
35: 3.4359738E10 35 4096.0
36: 6.8719477E10 36 8192.0
37: 1.37438953E11 37 16384.0
38: 2.74877907E11 38 32768.0
39: 5.4975581E11 39 65536.0
40: 1.09951163E12 40 131072.0
41: 2.19902326E12 41 262144.0
42: 4.3980465E12 42 524288.0
43: 8.796093E12 43 1048576.0
44: 1.7592186E13 44 2097152.0
45: 3.5184372E13 45 4194304.0
46: 7.0368744E13 46 8388608.0
47: 1.40737488E14 47 1.6777216E7
48: 2.81474977E14 48 3.3554432E7
49: 5.6294995E14 49 6.7108864E7
50: 1.12589991E15 50 1.34217728E8
51: 2.25179981E15 51 2.68435456E8
52: 4.5035996E15 52 5.3687091E8
53: 9.0071993E15 53 1.07374182E9
54: 1.80143985E16 54 2.14748365E9
55: 3.6028797E16 55 4.2949673E9
56: 7.2057594E16 56 8.5899346E9
57: 1.44115188E17 57 1.71798692E10
58: 2.88230376E17 58 3.4359738E10
59: 5.7646075E17 59 6.8719477E10
60: 1.1529215E18 60 1.37438953E11
61: 2.30584301E18 61 2.74877907E11
62: 4.611686E18 62 5.4975581E11
63: 9.223372E18 63 1.09951163E12
64: 1.8446744E19 64 2.19902326E12
65: 3.6893488E19 65 4.3980465E12
66: 7.3786976E19 66 8.796093E12
67: 1.4757395E20 67 1.7592186E13
68: 2.951479E20 68 3.5184372E13
69: 5.902958E20 69 7.0368744E13
70: 1.1805916E21 70 1.40737488E14
71: 2.3611832E21 71 2.81474977E14
72: 4.7223665E21 72 5.6294995E14
73: 9.444733E21 73 1.12589991E15
74: 1.8889466E22 74 2.25179981E15
75: 3.7778932E22 75 4.5035996E15
76: 7.5557864E22 76 9.0071993E15
77: 1.5111573E23 77 1.80143985E16
78: 3.0223145E23 78 3.6028797E16
79: 6.044629E23 79 7.2057594E16
80: 1.2089258E24 80 1.44115188E17
81: 2.4178516E24 81 2.88230376E17
82: 4.8357033E24 82 5.7646075E17
83: 9.6714065E24 83 1.1529215E18
84: 1.9342813E25 84 2.30584301E18
85: 3.8685626E25 85 4.611686E18
86: 7.7371252E25 86 9.223372E18
87: 1.54742505E26 87 1.8446744E19
88: 3.0948501E26 88 3.6893488E19
89: 6.1897002E26 89 7.3786976E19
90: 1.23794004E27 90 1.4757395E20
91: 2.4758801E27 91 2.951479E20
92: 4.9517602E27 92 5.902958E20
93: 9.9035203E27 93 1.1805916E21
94: 1.9807041E28 94 2.3611832E21
95: 3.9614081E28 95 4.7223665E21
96: 7.9228163E28 96 9.444733E21
97: 1.58456325E29 97 1.8889466E22
98: 3.1691265E29 98 3.7778932E22
99: 6.338253E29 99 7.5557864E22
100: 1.2676506E30 100 1.5111573E23
101: 2.5353012E30 101 3.0223145E23
102: 5.0706024E30 102 6.044629E23
103: 1.0141205E31 103 1.2089258E24
104: 2.028241E31 104 2.4178516E24
105: 4.056482E31 105 4.8357033E24
106: 8.112964E31 106 9.6714065E24
107: 1.6225928E32 107 1.9342813E25
108: 3.2451855E32 108 3.8685626E25
109: 6.490371E32 109 7.7371252E25
110: 1.2980742E33 110 1.54742505E26
111: 2.5961484E33 111 3.0948501E26
112: 5.192297E33 112 6.1897002E26
113: 1.0384594E34 113 1.23794004E27
114: 2.0769187E34 114 2.4758801E27
115: 4.1538375E34 115 4.9517602E27
116: 8.307675E34 116 9.9035203E27
117: 1.661535E35 117 1.9807041E28
118: 3.32307E35 118 3.9614081E28
119: 6.64614E35 119 7.9228163E28
120: 1.329228E36 120 1.58456325E29
121: 2.658456E36 121 3.1691265E29
122: 5.316912E36 122 6.338253E29
123: 1.0633824E37 123 1.2676506E30
124: 2.1267648E37 124 2.5353012E30
125: 4.2535296E37 125 5.0706024E30
126: 8.507059E37 126 1.0141205E31
127: 1.7014118E38 127 2.028241E31
float가 점점 커질 수록(exp 계산) 숫자 간격이 점점 커진다(ulp). 그래서 수치해석할 때, Math.ulp 메소드가 의미가 있을 수 있다. 따라서 float 형 (또는 double형)이 얼마나 큰 수가 될 수 있는지에 따라 신경을 써야할 수치해석이 필요한 것 같다.
'java core' 카테고리의 다른 글
Java8의 ArrayList.subList()한후 Iterate시 ConcurrentModificationException 발생 (0) | 2015.08.08 |
---|---|
Math.pow, 지수 비교 (Math.log, Math.getExponent) 공부 (0) | 2015.07.18 |
[Java8] slf4j logger를 Streams.forEach 사용시 에러 발생 처리 방법(peek) (0) | 2015.07.09 |
[Java8] Function과 Stream을 이용한 객체 복사 테스트 예제 (0) | 2015.07.04 |
Java의 도메인 캐시 TTL (networkaddress.cache.ttl / sun.net.inetaddr.ttl) (0) | 2015.06.07 |