2009.01.19 21:52
윈도우에는 계산기가 들어있다. 바로 calc다.
이 calc로 컴퓨터의 간단한 성능테스트를 할 수가 있다.

50000을 입력한 후 !(느낌표,Shift+1)를 입력한다.
!보면 알 수 있듯이 50000 factorial을 구하는 것이다.
50000*49999* ... * 1 이다. 곱하기 50000번 한다.
어쨌거나 요즘 잘나간다는 넷북으로 계산기 테스트를 해봤다.

삼성 NC10의 결과는 40초 이상이었다.
요즘 좀 최신형 피씨다 싶으면 17~18초 정도 나온다.
이 계산기는 싱글 코어만 사용하기 때문에, 하나의 코어에서 얼마나 빨리 계산할 수 있느냐를 나타낸다고 할 수있다.

50000! 의 결과는 다음과 같다.
위의 그림과 같이 213236승 정도의 단위이다.

한 가지 재밌는 점은 한 2년 정도전에 구입한 3.2Ghz Xeon이 두개 꼽혀 있는 연구실 컴퓨터에서 대략 8초 정도의 경이로운 속도가 나온 것이다. 이는 제온 cpu의 성능이 좋아서가 아니라(코어2듀오보다 느린 것같다)  Vista 64bit의 calc가 64bit로 돌아가기 때문인 것 같다.
제온 쿼드코어와 Windows 2003 x64가 설치되어 있는 서버에서도 calc는 64bit로 실행되며, 유사한 계산 속도를 보였다.

이에 자바로 50000!를 계산하면 어떤 결과가 나올 것인가가 궁금해졌다.
그래서 해봤다.
자바는 선에서 64bit OS용으로 배포되고 있는 것이다.

첫 번째, double을 이용해 계산해보았다. double을 64bit로 되어있다.
아래와 같이 계산 결과와 걸린 시간을 초단위로 나타내도록 했다.

...그러나 결과는 시궁창. 무한대가 나와버렸다.
갑자기 계산기 대단해 보인다.
그래서 BigInteger로 해봤다. 물론 계산기가 결과값은 부동소수점 수로 보여주고 있기 때문에, 부동소수점 계산을 하고 싶지만, BigFloat 등의 클래스는 보이지 않기 때문에, BigInteger로 해봤다. 정수 연산을 하니 당연히 정확도 100%다.
계산이 오래걸릴 것 같아서 진행정도를 확인하기 위해 중간에 i를 출력하고 있다.
그러나 역시 현실은 시궁창.
실행은 되었으나 결과를 출력하지 못한다. 아마 긴 길이의 String을 출력하는 데 문제가 생긴 것 같다. 이클립스에서 실행하고 있으니 이클립스 문제일 수 도있다.

어찌됐건 실행은 완료되었고, 시간은 11초가 걸렸다. 기대보다 훨씬 빨랐다.
계산이 제대로 되었는지 믿지 못하겠다면 다음과 같이 실행하면 된다.

이번엔 다행히 결과가 시궁창을 면했다. 맨 위에 있는 윈도우 계산기의 결과와 비교해보면 자리수가 일치함을 알 수 있다.
마지막으로 결과를 출력하는데 약간의 변화를 주었다.
계산기와 유사하게 출력하도록 했다.
결과는 3.347320509597144836915476094071486477912e+213236 이다.

계산기 결과와 비교해보면,
윈도우 계산기:          3.3473205095971448369154760940715e+213236
자바 BigInteger 계산: 3.347320509597144836915476094071486477912e+213236
그 결과가 일치하는 것을 확인할 수 있다.

사실 자바에서 BigInteger로 계산하면 메모리도 많이 먹고, 머하는지 모르겠는데, i값을 50000까지 출력하고 한참있다가 Result를 출력한다. BigInteger의 toString() 가 문제인가.
어쨌거나 64bit용 jvm이 64bit machine을 효율적으로 이용하고 있다는 것을 확인할 수 있었고, 사실 c로 작성되었을(모 어셈블리어로 작성되지는 않았겠지, 초기 paint가 assembly로 작성되었다나 모래나) 윈도우 계산기보다 그리 느리지 않은 성능을 보였다는 것은 고무적이다.

메인 메모리는 2기가를 사용하고 있으므로, 64bit의 진가를 느낀 것은 처음이다. ㅋ




Posted by 나야
2009.01.08 21:35
예를 들어 아래와 같은 코드가 있을 때,


이 코드를 실행시키면 int b = a; 에서 java.lab.NullPointerException이 발생합니다.
이것은 런타임에러기 때문에 당연히 이클립스에서는 잡아주지 못합니다.

무심코 int에 Integer를 넣고는 했는데 주의해서 사용해야 할 것 같습니다.


Posted by 나야
2009.01.06 12:21
java.util.Date는 날짜와 시간을 나타내기 위해 사용합니다.
이 클래스의 기본 생성자를 보면,
System.currentTimeMillis() 를 사용해서 초기화하고 있습니다.
System.currentTimeMillis() 를 보면,
http://java.sun.com/docs/glossary.html#N 를 보면 native keyword는 이 메소드가 자바가 아닌 다른 언어로 작성되었다는 것을 의미하는...
어쨌거나 milli second 정확도의 시간을 long값으로 반환하는데, 위에 나와있듯이 1970년 1월 1일 자정부터 현재시간과의 차이를 나타납니다.

일단 long값은 -9,223,372,036,854,775,808 에서 9,223,372,036,854,775,807 까지의 값을 가질 수 있으므로,
아래와 같이 해보면,
...

결과가 좀 아리까리합니다.
일단 Long.MAX_VALUE 값으로 테스트한 결과는 2억 9227만 8994년 까지 표현할 수 있음을 나타내고 있습니다.
인류가 2억년까지 멸종하지 않고 살아남을 수 있을까요. 일단 그때쯤 되면, 소형핵융합 엔진으로 우주 여행을 하고 있지 않을까 싶네요. 그정도면 자바는 이미 잊혀진 언어가 되있을테니 걱정할 필요는 없네요.
문제는 0과 Long.MIN_VALUE 값으로 테스트한 결과입니다.

먼저 0을 이용해 Date를 만들었더니, 1970년 1월 1일 9시로 나옵니다.
분명히 http://java.sun.com/javase/6/docs/api/java/util/Date.html 에는 January 1, 1970, 00:00:00 GMT 로 나와있는데요.
이것은 한국의 GMT offset이 +9 시간 이기 때문입니다. 그러니깐 아래와 같이 표준 시간대가 서울로 설정되어 있기 때문에 이렇게 표시해줍니다.


그리고 Long.MIN_VALUE 값의 결과에 대해 살펴보자면, 소스 코드를 봐야 하는데,
Date 클래스의 get 메소드는 getTime() 을 빼고는   사용하지 않게 되었기 때문에, SimpleDateFormat을 사용하고 있습니다. 이 SimpleDateFormat은 사용하기는 Simple하지만, 코드를 읽으려니, DateFormat을 extends하고 있고...

난  단지 단순히 음수를 어떻게 처리하고 있는지를 보고 싶을 뿐이고!
SimpleDateFormat코드는 2088 라인일 뿐이고!

어쨌든 쭉 따라가 보았습니다.
sdf.format(minDate) 에서 format(Date date) method는 DateFormat의 format(Date date) 인데 이 메소드는 abstract 메소드인 DateFormat 의 StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fiedlPosition)을 호출하고 있고 다시 이 메소드는 SimpleDateFormat에서 구현하고 있는데, 그 메소드가 다음 메소드입니다.
비스타 그림판에서 jpg로 저장하니 좀 뭉게지내요. 이 그림 위에껀 png,
어쨌건 다시
이 함수가 호출되고 있는데, 결국 SimpleDateFormat의 private method인 subFormat 메소드가 다시 호출됩니다.
근데 여기서 끝이 아니군요. 생각보다 더 복잡하네요. orz...나중에 시간있을 때 봐야 겠네요.

SimpleDateFormat 이 어떻게 돌아가는지는 무시하고,
SimpleDateFormat 을 이용하여 문자열로 변환할 수 있는 Date 혹은 long 값의 범위는 어디 까지 인가를 확인하기 위해서 long 값을 계속 줄여가면서 확인을 해보았습니다.

그 결과는 ..
0001-01-01 00:00:00.000 ( -62167424400000 ) 이 최소값입니다.
여기서 다시 -1을 하게 되면 날짜와 시간은 다시 증가하게 됩니다.
...
...?

결론!
  1. SimpleDateFormat은 0001-01-01 00:00:00.000 부터 제대로 표시할 수 있다.
  2. System.currentTimeMillis(), Date 등에서 사용되는 long값은 GMT offset이 0인 곳의 시각을 나타낸다.
- 추가
SimpleDateFormat 으로 문자열을 파싱할 때 알아둘 점이 있습니다.
위에 testStr 은 1월 32일을 의미하고 있습니다. ㅡㅡㅋ 그렇죠, 1월에는 32일이 없습니다.
제가 이 코드를 돌려본 이유는 날짜 규칙(1월은 31일까지 있다, 윤년 등등...)이 SimpleDateFormat에 구현되어 있는지 확인하기 위해서 입니다. 위 코드를 돌려보면,
위와 같이 2월 1일이 표시됩니다.
결과적으로 SimpleDateFormat은 ParseException 을 던지지 않았고, 2009년 1월 32일은 2월 1일로 제대로(?) 파싱된 것을 확인할 수 있습니다....
날짜 규칙을 확인하는 코드는 따로 구현해야겠네요.

Posted by 나야
2008.07.06 15:23
사용자 삽입 이미지
Arthur : van Hoff
Sun의 자바 개발 팀. 검색해보면 이 사람에 관한 글을 많이 볼 수 있음.
왼쪽에 있는 사람이 van Hoff.
딱 봐도 고수같다.







primivite type boolean 의 Wrapper Class.
Serializable 인터페이스와 Comparable<Boolean> 을 구현

Comparable<Boolean> Interface Implementation
사용자 삽입 이미지

이 코드가 좀 독특한데, Comparable Interface의 JavaDoc을 보면, 두 클래스의 natural order가 같을 경우 0을, less than 일 경우 음수를, greater than 일 경우 양수를 반환한다. 이 method는 Collections.sort를 이용하여 List 또는 배열을 정렬할 수 있다.
ArrayList<Integer>를 이용해 간단히 테스트를 해보면, Collensions.sort는 less instance 부터 정렬하는 것을 알 수 있다. 그리고 ArrayList<Boolean> 으로 테스트해보면, false --> true로 정렬이 된다. 위의  compareTo method의 구현에서 보듯이 삼항연산자는 참 편리한 것같다. 이해도 잘된다.

또 독특한게 있는데, hashCode()이다.
사용자 삽입 이미지
true의 hashcode 는 1231을, false는 1237을 반환한다. 응?
http://community.livejournal.com/ru_programming/964630.html에 러시아 말로 다음과 같이 써있다.(러시아->영어로 구글번역이용)
아마도 이런 이유가 아닐까요.
true : 1+2+3+1 = 7 는 행운의 숫자
false : 1+2+3+7 = 13 는 불길한 숫자
밑에 댓글을 읽어보니, 그냥 농담인 것 같다. 그냥 van hoff에게 물어보면 좋을텐데.

쭉 둘러보니, 다른 특이한 점은 없다.















Posted by 나야
2008.03.31 20:04
Arrays는 7 미만의 작은 배열의 경우 insertion sort를 하고,
integer 등의 정수는 merge sort를
float 등의 부동 소수점 수는 quick sort를 합니다.

시작은 Collections.sort(List<T> lis즘t, Comparator<? supter T>) 에서 하겠습니다.
Collections class의 소스코드를 보시면
사용자 삽입 이미지
Arrays.sort()를 호출하고 있습니다.
이제 그럼 Arrays.sort로 가보겠습니다.
Arrays class의 api를 보시면, byte, char, double, float, int, long,  short, Object 그리고 Generic T의 배열에 대해 Sort method를 정의해 놓은 것을 확인하실 수 있습니다.

우선 위에서 사용된 Arrays.sort(Object[], Comparator)를 먼저 살펴보겠습니다.
이 method의 API를 읽어보면,
정렬의 결과가 stable하며, 수정된 merge sort를 사용한다고 되어 있습니다.
작은 쪽 리스트의 가장 큰 값이 큰 쪽 리스트의 가장 작은 값보다 작으면 merge를 생략하도록 수정되어 있다고 나와 있습니다.그리고 merge sort가 그렇듯, n*log(n) performance를 보장한다고 되어 있습니다.

자 그럼 ArrayList.sort(Object[], Comparator) method의 source code를 살펴보겠습니다.
사용자 삽입 이미지
바로 mergeSort를 하고 있습니다. 자 그럼 바로 mergeSort(Object[] src, Object[] dest, int low, int high, int off) 의 declaration이 있는 곳으로 가겠습니다.
사용자 삽입 이미지
흠. 이제 재밌는 부분이 나왔네요.
작은 배열은 Insertion Sort를 하게 되어 있습니다.
INSERTIONSORT_THRESHOLD 값은 static final int 타입으로 7이 선언되어 있습니다.
왜 7인지는 잘 모르겠습니다. 어쨌거나 7보다 작으면 Insertino Sort를 하게 되어 있습니다.

제일 먼저 정렬할 배열의 크기를 확인하고, 충분히 작으면 Insertion Sort를 하고 return; 이 호출됩니다. 그렇지 않을 경우, Merge Sort를 하게 되며, 배열을 반으로 나누어 Merge Sort를 하게 됩니다.
그런데 잘 사용하지 않은 operator가 나왔습니다.
>>>  이 operator를 뭘하는 걸까요. 찾아보니 unsigned bit shift right이네요. 응? 그게 모지..
java spec을 읽어봐야 할 것 같아서 패스하겠습니다.
일단 floor( the greatest integer less thatn or equal to )의 의미로 알고 넘어가겠습니다.

recursive 하게 mergeSort를 호출한다음,
merge하거나 그냥 Destination Array에 복사하거나 입니다.

그런데 Arrays class에는 정말 재밌어 보이는 method들이 많네요.
천천히 계속 살펴봐야겠습니다.
이런 소스가 그냥 공개되어 있다는 것이 신기할 뿐입니다. ^^:;;;
Posted by 나야
2008.03.07 10:31
구글에서 검색해보니

Inet Address inetaddr = InetAddress.getLocalHost();
inetaddr.getHostAddress();

를 리눅스에서 사용하면,  127.0.0.1을 반환해 주는데, 이 주소는 LoopBack 주소를 말합니다.
윈도우에서는 실제 설정해놓은 ip를 반환한다고 합니다.
LoopBack 주소를 반환하는 것은 합당하다는 글이 좀 있었는데.
어쨌거나 제가 하고 싶은 것은 메시지 기반 통신에서 필요할 때마다 ServerSocket을 띄우고 메시지를 받을 Agent에게 접속할 ip와 port를 알려주어서 Binary File을 받아가게 하고 싶은 것입니다.

이를 위해서 NetworkInterface.getNetworkInterfaces()를 사용했습니다.
이 정적 메쏘드를 사용하면 시스템이 갖고 있는 NetworkInterface들을 Enumeration<NetworkInterface>로 반환해주는데, 이를 확인해보면 ip를 확인할 수 있습니다.

Enumeration<NetworkInterface> ne = NetworkInterface.getNatworkInterfaces();
while ( ne.hasMoreElements()) {
     NetworkInterface ni = ne.nextElement();
     System.out.println("Name : " + ni.getName());
     Enumeration<InetAddress> inets = ni.getInetAddresses()/;
     while(inets.hasMoreElements();
          InetAddress iaddr = inets.nextElement();
          System.out.println("INet --> isSiteLocalAddress() -->" + iaddr.isSiteLocalAddress());
     }
}

간략히 위와 같은 식으로 해서 NetworkInterface의 이름이 regular expression "eth[0-9]'인 것을 찾은 다음, isSiteLocalAdresss()를 통해 true인 것을 확인하면, local ip를 확인할 수 있습니다.

검색한 글에서 추천하는 방법은 외부와의 socket연결이 되어 있다면 그 socket연결을 통해서 ip를 확인하는 방법이 좋다고 합니다.

꼼수꼼수...
Posted by 나야
2008.01.24 02:35
학교 프로젝트에서 만들고 있는 자바 프로그램의 패키지 이름을 어떻게 만들까 생각하다가, 구글에서 검색해서
에 들어갔다가 여기서 다시
에 들어갔습니다. 아래 내용은 위 페이지의 내용과 같습니다.(거의)



그런데 생각해보니, 자바는 유니코드를 사용해서, 한글 변수명도 사용할 수 있습니다.
한글 변수를 사용하는 사람을 없겠지요..ㅡㅡㅋ
'한글 자바 관습적 이름 짓기' 이런...것이...
사실 reserved keyword 가 영어므로,
영어는 만국 공용어 쓰읍.. 기분 울적.
기분 전환용 사진입니다. 상큼발랄.
사용자 삽입 이미지



Posted by 나야