'자바 숫자'에 해당되는 글 1건

  1. 2006.12.20 자바 숫자 표현

간혹 타입을 결정할때 아리송할때가 있다.

정확한 범위를 알고 필요한 타입을 쓰자


1. int형으로 하면 얼마까지 나타낼 수 있는가?

  int형으로 했을 경우 Test해 본 결과로는 21억까지 밖에 계산이 안되네요.
  즉, 2,147,483,647 을 아래처럼 해 봤죠.

   int result = Integer.parseInt("2147483646") + 1;
  은 제대로 계산이 되는데,
   int result = Integer.parseInt("2147483647") + 1;
  의 값은  -2147483648이 나오네요...

  2,147,483,647 은 2^(32-1) -1 입니다.

2. 그럼 long형으로 하면 얼마까지 가능할까?

  long형은 9,223,372,036,854,775,807 까지 됩니다.
  '조' 다음이 '경'이니까 9백2십2경 3천조 까지구낭...
   long result = Long.parseLong("9223372036854775807 ) + 1;

  9223372036854775807 + 1 은 -9223372036854775808 로 나오네요.
 
  9223372036854775807 은 2^(64-1)-1 입니다.
 

[결론] 따라서 21억 이상을 표현하려면 long형이 필요함을 알수 있습니다.
  만약 소수점 이하 자릿수도 표현해야 한다면 double형이 필요합니다.
  double형으로 했을 경우도 반드시 만능이 아닙니다.

3. 그럼 자바의 최대 소수점 처리가 가능한 double형은 어디까지인가요?

1)소수 이하의 자리수를 유효숫자 2자리까지 필요하다면 그 수치는
  70조(70,368,744,177,663.99) 까지 입니다.
  아래와 같은 프로그램에서

  import java.text.DecimalFormat;
  DecimalFormat df = new DecimalFormat("#########################.00");
  double d = new Double(src.getText()).doubleValue();
  d += 0.01;
  textfield.setText(df.format(d) );

  70368744177663.99 + 0.01 = 70368744177664 로 제대로 계산되나
  70368744177664.00 + 0.01 = 70368744177664.02 로 0.01의 오차가 발생합니다.

2)만약 double형으로 사용하되 소숫점 이하는 무시한다고 한다면
  9천 7조(9,007,100,000,000,000) 까지만 + 1.0 을 했을 때 정확한 수치가 나옵니다.

3)만약 소수이하 세자리까지 필요하다면 어디까질까요?

  8조 7천9백60억(8,796,093,022,207)까지네요.
  8796093022207 + 0.001 = 8796093022207.001 로 정확하나
  그 다음부턴 0.001의 차이가 납니다.

  (NOTE: 심각하게 차이가 바로 발생하지는 않지만 위 수치 부터 덧셈이나 뺄셈이 약간의
         오차를 보이기 시작합니다.)

  [결론] 에궁 자바는 double외에는 없는데, 어떻하낭? 소수이하를 무시하면 9천 7조 까지만
       계산이 정확하고, 소수 두자리 까진 70조가 넘어면 안되구, 소수 세째자리가진
       8조7천억이 넘어면 안된다더라...
       어쩌나...
       그러나 어디까지라고는 꼭 집어 얘기하진 못하지만, 국방부 같이 몇 백억 단위는
       long형과 double형만으로 계산으로 하여도 문제는 발생하지 않겠네요..

       그러나 은행이나, 금융기관, 국가재정을 다루는 시스템을 꾸밀 때,
       만약 그 시스템이 자바로 되어 있다면,
       수치가 조단위를 를 넘어 갈 경우 long과 double형을 사용하면 계산이
       틀려진다는 걸 꼭 기억하세요.



4. 근데, java.math.BigDecimal 은 뭐하는 거예요?
  java.math.BigInteger도 있던데?

  import java.math.BigDecimal;
  BigDecimal op1 = new BigDecimal("100000000000000000000000000000000000.01");
  BigDecimal op2 = new BigDecimal("10002341234124000000000000000000.2134");
  BigDecimal sum = op1.add(op2);
  textArea.setText(sum.toString());
 
  등과 같이 사용하는데, 아무리 큰 수 일지라도 완벽하게 계산해 냅니다.
  java.math.BigInteger 는 정수형을 계산한다는 것을 제외하고 똑 같습니다.
 
  NOTE: 그러나, 경우에 따라, divide연산의 무한소수의 경우는 여전히 자릿수 고민을 하셔야
      하고, 연산을 위한 성능적인 이슈도 함께 고려되어야 겠지요.

[진짜 결론]
  날로 통화화폐가치가 떨어 지는 요즘 조단위는 심심찮게 신문에 등장하는 수치입니다.
  이젠 천문학적인 숫자가 아니라 일상적인 숫자로 되는 요즘 돈계산을 하실 때,
  아무 생각없이 사칙연산을 할 것이 아니라 보다 유효자리숫자를 고려하여 연산을
  생각하는 꼼꼼한 프로그래머가 됩시다.... ;

  마지막으로 건의를 주신 이원경님께 감사드리며 반영하도록 해야 겠네요.

[PS] 자바의 Default Decimal 형은 float형이 아니라 double형입니다.
  즉 float f = (float) 5.0; 등과 같이 cast연산자를 사용하는 반면에
    double d = 5.0;  이렇게 사용할 수 있는 거죠.
  구태여 자바에서 float형을 쓸 일은 없다고 보여집니다. 유효숫자 자리수만 낮아질 뿐이죠.

자바서비스넷 이원영
------------------------------------------------------- 
  본 문서는 자유롭게 배포/복사 할 수 있으나 반드시
  이 문서의 저자에 대한 언급을 삭제하시면 안됩니다


1) 내부적 연산은 허용된(!) 유효숫자 범위 내에서 가급적 정확하게 하고,
2) 화면으로의 표현은 적절한(!) 범위 내에서 표현하면 되는 것이지요.

1)번의 의미는, 예를 들어 어떤 경우로도 1/3 = 0.33333333....이므로,
float, double, java.math.BigDecimal 등이 허용하는 오차 범위가, 해당 비즈니스적인
면에서 충분하냐에 따라 결정하면 된다는 것이지요.

2)번의 의미는 사칙연산은 앞서와 같이 하면 되는데, 어느 순간이 되면 화면이나 파일과
같이 문자열 형태로 표현되어야 할 시점이 있을 것입니다. 이 경우는 적절한 소숫점
이하 몇자리로 표현하면 사용하면 되는 것이지요.

제목 : Re: Java Float형으로 표현가능한 가장 큰 자연수
글쓴이: 이원영(javaservice) 2003/02/04 23:23:12 조회수:578 줄수:81
IEEE 754 규약에 따른 부동 소수점의 싱글 포맷 형인 자바의 4byte  float형에서
소숫점 이하를 버린 자연수 중, 표현가능한 가장 큰 수는 2의 24승인
16,777,216 입니다.

31               23               15               7             0
S e e e e e e e  e 0 0 0 0 0 0 0  0 0 0 0 0 0 0 0  0 0 0 0 0 0 0 0
| |              | |                                             |
| +-- exponent --+ +---------significand(mantissa)---------------+
|
+- sign bit

- Bit 31 (the bit that is selected by the mask 0x80000000) represents the sign of
  the floating-point number. 
- Bits 30-23 (the bits that are selected by the mask 0x7f800000) represent
  the exponent. 
- Bits 22-0 (the bits that are selected by the mask 0x007fffff) represent
  the significand (sometimes called the mantissa) of the floating-point number. 
- positive infinity, the result is 0x7f800000
- negative infinity, the result is 0xff800000
- NaN, the result is 0x7fc00000
- let s, e, and m be three values that can be computed from the argument: 

 int s = ((bits >> 31) == 0) ? 1 : -1;
 int e = ((bits >> 23) & 0xff);
 int m = (e == 0) ?
                 (bits & 0x7fffff) << 1 :
                 (bits & 0x7fffff) | 0x800000;

 number value = s·m·2^(e-150)

E:\temp>java Test
Float.MAX_VALUE=2147483647
2^0 i:1         s:1     e:127   m:8388608       s*m*2^(e-150)=1
2^1 i:2         s:1     e:128   m:8388608       s*m*2^(e-150)=2
2^2 i:4         s:1     e:129   m:8388608       s*m*2^(e-150)=4
2^3 i:8         s:1     e:130   m:8388608       s*m*2^(e-150)=8
2^4 i:16        s:1     e:131   m:8388608       s*m*2^(e-150)=16
2^5 i:32        s:1     e:132   m:8388608       s*m*2^(e-150)=32
2^6 i:64        s:1     e:133   m:8388608       s*m*2^(e-150)=64
2^7 i:128       s:1     e:134   m:8388608       s*m*2^(e-150)=128
2^8 i:256       s:1     e:135   m:8388608       s*m*2^(e-150)=256
2^9 i:512       s:1     e:136   m:8388608       s*m*2^(e-150)=512
2^10 i:1024     s:1     e:137   m:8388608       s*m*2^(e-150)=1024
2^11 i:2048     s:1     e:138   m:8388608       s*m*2^(e-150)=2048
2^12 i:4096     s:1     e:139   m:8388608       s*m*2^(e-150)=4096
2^13 i:8192     s:1     e:140   m:8388608       s*m*2^(e-150)=8192
2^14 i:16384    s:1     e:141   m:8388608       s*m*2^(e-150)=16384
2^15 i:32768    s:1     e:142   m:8388608       s*m*2^(e-150)=32768
2^16 i:65536    s:1     e:143   m:8388608       s*m*2^(e-150)=65536
2^17 i:131072   s:1     e:144   m:8388608       s*m*2^(e-150)=131072
2^18 i:262144   s:1     e:145   m:8388608       s*m*2^(e-150)=262144
2^19 i:524288   s:1     e:146   m:8388608       s*m*2^(e-150)=524288
2^20 i:1048576  s:1     e:147   m:8388608       s*m*2^(e-150)=1048576
2^21 i:2097152  s:1     e:148   m:8388608       s*m*2^(e-150)=2097152
2^22 i:4194304  s:1     e:149   m:8388608       s*m*2^(e-150)=4194304
2^23 i:8388608  s:1     e:150   m:8388608       s*m*2^(e-150)=8388608
2^24 i:16777216 s:1     e:151   m:8388608       s*m*2^(e-150)=16777216
Max Float=16777216

new Float(16777216)=16777216
new Float(16777217)=16777216

Posted by [czar]
,