실수 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형)이 얼마나 큰 수가 될 수 있는지에 따라 신경을 써야할 수치해석이 필요한 것 같다.





Posted by '김용환'
,