자바에서 for 문은 가장 빈번하게 사용되는 반복문입니다.

 

반복적인 업무를 처리하기 때문에 배열 또는 ArrayList 등과 함께 자주 사용되고

 

for 문에서 이용하는 변수는 배열의 인덱스로 겸용되어 쓰여지는 경우가 많이 있습니다.

 

< for 문의 기본 형식 >

 

for (초기화식; 조건식; 업데이트식)

실행부분;

 

1
2
3
4
5
6
7
8
9
public class ForTest {
    
    public static void main(String[] args) {
        int array[] = {1020304050};
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
    }
}
cs

 

 

이렇게 함께 사용되는 경우가 많아져서 JDK 5.0 버전부터는 향상된 for 문을 지원하고 있습니다.

 

< for each 문의 형식 >

 

for (변수타입 변수이름 : 배열이름)

실행부분;

 

1
2
3
4
5
6
7
8
9
public class ForTest {
    
    public static void main(String[] args) {
        int array[] = {1020304050};
        for (int number : array) {
            System.out.println(number);        
        }
    }
}
cs

 

for each (향상된 for 문) 에서는 배열의 항목 수만큼 실행부분을 반복하는데

반복이 이루어질 때마다 배열의 항목을 순서대로 꺼내어 변수(number) 에 자동으로 대입해 줍니다.

 

따로 반복 변수(int i) 를 선언하거나 배열의 값을 가져오는 부분(array[i]) 없이

실행부분에서는 하고자 하는 작업에 집중할 수 있습니다.

 

위의 두 개의 소스코드는 결국 동일한 결과를 출력하게 됩니다.

 

 

자바 for each 문을 사용할 때 주의해야 할 점은

오직 배열의 값을 가져다 사용할 수만 있고(read) 수정할 수 는 없다는 것(write) 입니다.

 

(추가적으로 for 문과 for each 문의 구현 방식에 대한 성능 차이는 없다고 볼 수 있습니다.)

 

Posted by maze1008
,

자바(Java) 에 대해 공부하면서 다음과 같은 말을 많이 들어보았을 것입니다.

 

깊은 복사(deep copy) 와 얕은 복사(shallow copy)

참조 복사(call by reference) 와 값 복사(call by value)

 

값을 다른 곳에 복사하여 사용할 때, 복사가 이루어지는 방법에 따라 동작에 많은 영향을 미치게 됩니다.

지금부터 ArrayList 를 사용하여 두 가지 방법이 어떤 차이점을 가지고 있는지 알아보도록 하겠습니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import java.util.ArrayList;
 
public class CopyTest {
    static ArrayList<String> source = new ArrayList<String>();
    static ArrayList<String> destination = new ArrayList<String>();
    
    public static void initArrayList() {
        if (null != source) {
            source.clear();
            source.add("apple");
            source.add("banana");
            source.add("cherry");
        }
 
        if (null != destination) {
            destination.clear();
        }
    }
    
    public static void printArrayList() {
        System.out.println("====== source result ======");
        for (int i = 0; i < source.size(); i++) {
            System.out.println("source ["+i+"] : " +source.get(i));
        }
 
        System.out.println("====== destination result ======");
        for (int i = 0; i < destination.size(); i++) {
            System.out.println("destination ["+i+"] : " +destination.get(i));
        }
    }
 
    public static void main(String[] args) {
        initArrayList();
 
        // TODO : operation
        
        printArrayList();
    }
}
 
cs

 

 

코드를 간단히 살펴보면,  2 개의 ArrayList 가 선언되어 있고(source, destination)

main() 메소드의 // TODO : operation  위치에서 다음과 같은 2가지 동작을 수행한 후

각각의 ArrayList 가 가지고 있는 값을 모두 출력하게 됩니다. 

1. source 에 있는 내용을 destination 에 복사

2. destination 에 항목을 1개 추가

 

 

동일한 동작을 얕은 복사와 깊은 복사로 적용해 보았습니다.

1. 얕은 복사(shallow copy)      

destination = source;

destination.add("kiwi");

  

<결과>

destination 에만 추가한 kiwi 가 source 에도 추가되어 있음을 확인할 수 있습니다.

shallow copy 는 원본과 복사본 둘 중 한쪽의 수정이 양쪽에 모두 영향을 미치게 됩니다.

 

====== source result ======
source [0] : apple
source [1] : banana
source [2] : cherry
source [3] : kiwi 
====== destination result ======
destination [0] : apple
destination [1] : banana
destination [2] : cherry
destination [3] : kiwi

 

2. 깊은 복사(deep copy)      

destination.addAll(source) ; // 또는 destination =(ArrayList<String>)source.clone();

destination.add("kiwi");

  

<결과>

destination 에만 추가한 kiwi 가 source 에는 존재하지 않음을 확인할 수 있습니다.

deep copy 는 원본과 복사본 둘 중 한쪽의 수정이 다른 한쪽에 영향을 미치지 않습니다.

주석으로 표기한 방법으로도 같은 효과를 얻을 수 있습니다.

 

====== source result ======
source [0] : apple
source [1] : banana
source [2] : cherry
====== destination result ======
destination [0] : apple
destination [1] : banana
destination [2] : cherry
destination [3] : kiwi

 

 

 

그런데 여기서 추가적으로 1가지 더 살펴 보아야 하는 부분이 있습니다.

ArrayList  의 Item 으로 객체가(Object) 선언되어 있다면 깊은 복사는 어떻게 동작하게 될까요?

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.util.ArrayList;
 
class Fruit {
    private String name;
    private int count;
 
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
}
 
public class CopyTest {
    static ArrayList<Fruit> source = new ArrayList<Fruit>();
    static ArrayList<Fruit> destination = new ArrayList<Fruit>();
    
    public static void initArrayList() {
        if (null != source) {
            source.clear();
            
            String[] names = new String[] {"apple""banana""cherry"};
            for (int i = 0; i < names.length; i++) {
                Fruit f = new Fruit();
                f.setName(names[i]);
                f.setCount(i + 1);
                source.add(f);
            }
        }
 
        if (null != destination) {
            destination.clear();
        }
    }
    
    public static void printArrayList() {
        System.out.println("====== source result ======");
        for (int i = 0; i < source.size(); i++) {
            System.out.println("source["+i+"] name:"+source.get(i).getName());
            System.out.println("source["+i+"] count:"+source.get(i).getCount());
        }
 
        System.out.println("====== destination result ======");
        for (int i = 0; i < destination.size(); i++) {
            System.out.println("destination["+i+"] name:"+destination.get(i).getName());
            System.out.println("destination["+i+"] count:"+destination.get(i).getCount());
        }
    }
 
    public static void main(String[] args) {
        initArrayList();
        
         // TODO : operation
 
        printArrayList();
    }
}
cs

 

코드를 간단히 살펴보면, name 과 count 를 속성으로 갖고 있는 Fruit 클래스가

2 개의 ArrayList 의(source, destination) Item 으로 선언되어 있습니다.

마찬가지로 main() 메소드의 // TODO : operation  위치에서 다음과 같은 2가지 동작을 수행한 후

각각의 ArrayList 가 가지고 있는 값을 모두 출력하게 됩니다. 

1. source 에 있는 내용을 destination 에 복사

2. destination 에 항목을 1개 추가

 

 

동일한 동작을 얕은 복사와 깊은 복사로 적용해 보았습니다.

1. 얕은 복사(shallow copy)      

destination = source;

Fruit f = new Fruit();

f.setName("kiwi");

f.setCount(4);

destination.add(f);

  

<결과>

destination 에만 추가한 kiwi 가 source 에도 추가되어 있음을 확인할 수 있습니다.

shallow copy 는 원본과 복사본 둘 중 한쪽의 수정이 양쪽에 모두 영향을 미치게 됩니다.

 

====== source result ======
source [0] name : apple
source [0] count : 1
source [1] name : banana
source [1] count : 2
source [2] name : cherry
source [2] count : 3
source [3] name : kiwi
source [3] count : 4
====== destination result ======
destination [0] name : apple
destination [0] count : 1
destination [1] name : banana
destination [1] count : 2
destination [2] name : cherry
destination [2] count : 3
destination [3] name : kiwi
destination [3] count : 4

 

2. 깊은 복사(deep copy)     

destination.addAll(source) ; // 또는 destination =(ArrayList<Fruit>)source.clone();

Fruit f = new Fruit();

f.setName("kiwi");

f.setCount(4);

destination.add(f);

  

<결과>

destination 에만 추가한 kiwi 가 source 에는 존재하지 않음을 확인할 수 있습니다.

deep copy 는 원본과 복사본 둘 중 한쪽의 수정이 다른 한쪽에 영향을 미치지 않습니다.

주석으로 표기한 방법으로도 같은 효과를 얻을 수 있습니다.

 

====== source result ======
source [0] name : apple
source [0] count : 1
source [1] name : banana
source [1] count : 2
source [2] name : cherry
source [2] count : 3
====== destination result ======
destination [0] name : apple
destination [0] count : 1
destination [1] name : banana
destination [1] count : 2
destination [2] name : cherry
destination [2] count : 3
destination [3] name : kiwi
destination [3] count : 4

 

 

이것만으로 정말 제대로 된 Fruit 객체에 대한 깊은 복사가 이루어 진 것일까요?

source 의 apple 객체의 count 를 1 에서 10 으로 값을 바꾼다면 destination 에는 영향이 없을까요?

다시 테스트를 진행해 보도록 하겠습니다.

 

* 객체의 깊은 복사(deep copy)

destination.addAll(source) ; // 또는 destination =(ArrayList<Fruit>)source.clone();

Fruit f = destination.get(0);    // "apple"

f.setCount(10);                    // change : 1 -> 10

  

<결과>

분명히 깊은 복사를 진행했는데도 source 와 destination 의 apple 의 count 가 모두 10으로 변경된 것을 확인할 수 있습니다. 결국 두 ArrayList 의 포함된 Fruit 은 같은 객체라는 의미입니다.

 

====== source result ======
source [0] name : apple
source [0] count : 10
source [1] name : banana
source [1] count : 2
source [2] name : cherry
source [2] count : 3
====== destination result ======
destination [0] name : apple
destination [0] count : 10
destination [1] name : banana
destination [1] count : 2
destination [2] name : cherry
destination [2] count : 3

 

이 문제를 해결하기 위해서는 결국 다음과 같은 방법이 필요합니다.

 

* 객체의 깊은 복사(deep copy)

1. Fruit 클래스의 복사 생성자 추가

public Fruit() { }      // 기본 생성자

public Fruit(Fruit f) { // 복사 생성자

   this.name = f.getName();
   this.count = f.getCount();

 }

 

2. main() 메소드에서 객체에 대한 깊은 복사(deep copy) 수행

for (int i = 0; i < source.size(); i++) {
        destination.add(new Fruit(source.get(i)));
}
Fruit f2 = destination.get(0);    // "apple"
f2.setCount(10);                    // change : 1 -> 10

  

<결과>

원본과 복사본 둘 중 한쪽의 수정이 다른 한쪽에 영향을 미치지 않습니다.

이제서야 완전히 독립된 ArrayList 객체 복사가 완료되었습니다.

 

====== source result ======
source [0] name : apple
source [0] count : 1
source [1] name : banana
source [1] count : 2
source [2] name : cherry
source [2] count : 3
====== destination result ======
destination [0] name : apple
destination [0] count : 10
destination [1] name : banana
destination [1] count : 2
destination [2] name : cherry
destination [2] count : 3

 

Posted by maze1008
,

자바에서는 Random 클래스와 Math 클래스를 사용하여 편리하게 random value 를 생성할 수 있습니다.

자바 랜덤함수(Java Random)

 

 

그러나 랜덤 문자열(random string) 을 만들기 위해서는 추가적으로 간단한 구현이 필요합니다.

지금부터는 random string 을 만들기 위한 방법에 대해 설명하도록 하겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.Random;
 
public class RandomString {
    private static final char[] chars;
    static {
        StringBuilder buffer = new StringBuilder();
        for (char ch = '0'; ch <= '9'; ++ch)
            buffer.append(ch);
        for (char ch = 'a'; ch <= 'z'; ++ch)
            buffer.append(ch);
        for (char ch = 'A'; ch <= 'Z'; ++ch)
            buffer.append(ch);
        chars = buffer.toString().toCharArray();
    }
 
    public static String random(int length) {
        if (length < 1)
            throw new IllegalArgumentException("length < 1: " + length);
 
        StringBuilder randomString = new StringBuilder();
        Random random = new Random();
        
        for (int i = 0; i < length; i++) {
            randomString.append(chars[random.nextInt(chars.length)]);
        }
        return randomString.toString();
    }
 
    public static void main(String[] args) {
        System.out.println(random(10));
    }
}
cs

 

위의 random() 메소드는 글자의 길이(length) 를 파라미터로 입력 받아

원하는 크기의 random string 생성하고 있습니다.

 

chars 배열을 통해 원하는 문자(숫자, 소문자, 소문자)들을 기초로 하여

Random 클래스의 nextInt() 메소드에서 발생시키는 위치의 배열 값을 차곡차곡 쌓아

지정된 길이 만큼의 string 을 생성해서 반환합니다.

 

이외에도 "~!@#$%^&*()_+{}|\\\"`;:'<>?,./=-[]" 와 같은 특수 기호들을 포함할 수도 있습니다.

 

<출력>

3ifL5KImXd

 

 

추가적으로 stackoverflow 를 통해서 더 다양한 방법을 확인 할 수 있습니다.

 

 

Posted by maze1008
,

자바 랜덤함수를 사용하는 방법은 2가지가 있습니다.

 

Random 클래스와 Math 클래스를 각각 사용해서 random value 를 생성하는 방법에 대해 설명 드리겠습니다.

 

 

1. Java.util.Random

 

Random 클래스의 객체를 생성하면 다음과 같이 다양한 메소드를 사용하여 원하는 타입의 random value 를 생성할 수 있습니다.

 

그 중에서도 가장 많이 사용되는 nextInt() 메소드는 파라미터를 사용해서

원하는 범위내의 양수 값을 (범위 : 0 ~ 파라미터-1) 가져올 수 있습니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.util.Random;
 
public class RandomTest {
    public static void main(String[] args) {
        Random random = new Random();
        
        System.out.println(random.nextBoolean());   // true or false
        System.out.println(random.nextFloat());     // range : 0.0f ~ 1.0f(exclusive)
        System.out.println(random.nextInt());       // all 2^32 possible int values 
        System.out.println(random.nextInt(100));    // range : 0 ~ 99
    }
}
 
cs

 

 

<결과>

false
0.2699461
2087110484
73

 

 

 

2. Java.util.Math

 

Math 클래스는 수학적 연산과 관련된 메소드들을 제공하는 클래스로

random() 메소드를 사용하여 0.0 <= double value < 1.0  의 값을 생성할 수 있습니다.

 

random() 메소드가 double 타입을 리턴하기 때문에 타입 캐스팅(int)를 사용해서 정수형으로 변환하여 사용할 수 있으며, (int)(Math.random() * 최대값) + 최소값 의 연산을 통해 최소값 ~ 최대값의 범위 지정도 가능합니다. (실제적으로는 (int)(Math.random() * (최대값 - 최소값 + 1)) + 최소값  입니다.)

 

예제에서는 1 ~ 100 사이의 random value 를 출력하게 됩니다.

 

1
2
3
4
5
6
7
8
public class RandomTest {
    public static void main(String[] args) {
        // range : 0.0 ~ 1.0(exclusive)
        double randomValue = Math.random();    
        int intValue = (int)(randomValue * 100) + 1;
        System.out.println(intValue);
    }
}
cs

 

<결과>

75 

 

 

Posted by maze1008
,

자바의 String 형을 선언하는 방법에는 2가지가 있습니다.

 

1. 기본 자료형(Primitive Type) : 실제 값을 저장

String apple = "apple";

 

2. 참조형(Reference Type) : 클래스를 사용하여 값이 저장되어 있는 주소를 저장

String banana = new String("banana");

 

두 가지 모두 애용되는 방법이지만

문자열을 비교하는 연산을 수행할 때 원하지 않는 오류를 발생시킬수 도 있습니다.

 

오늘은 기본 자료형과 참조형에 대한 등위 연산자의 차이와

문자열 비교에 이용되는 다양한 String 메소드에 대해서 알아 보도록 하겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class StringTest {
    
    public static void printResult(boolean result) {
        if (result) {
            System.out.println("같다");
        } else {
            System.out.println("다르다");            
        }
    }
 
    public static void main(String[] args) {
        // 기본 자료형(primitive type)
        String str1 = "apple";
        String str2 = "apple";
                
        // 참조형(reference type) : class
        String str3 = new String("apple");
        String str4 = new String("apple");
 
        // 등위 연산자( == )
        printResult(str1 == str2);        
        printResult(str2 == str3);
 
        // equals(), equalsIgnoreCase()
        printResult(str2.equalsIgnoreCase(str3));
        printResult(str3.equalsIgnoreCase(str4));
 
        // compareTo(), compareToIgnoreCase()
        printResult(str2.compareToIgnoreCase(str3) == 0);
        
        // matches(regex)
        printResult(str2.matches(str3));
    }
}
 
cs

 

"apple" 이라는 문자열을 대해 기본 자료형 변수와(str1, str2) 참조형 변수(str3, str4) 가 각각 2개씩 선언하였습니다.

 

 

1. 등위 연산자 ( == )

 

첫 번째로 비교에서 가장 많이 사용되는 등위 연산자를 적용해 보았습니다.

 

1
2
3
// 등위 연산자( == )
printResult(str1 == str2);    // 같다
printResult(str2 == str3);    // 다르다
cs

 

같은 기본 자료형을 비교했을 때에는 "같다"

기본 자료형과 참조형을 비교했을 때에는 "다르다"는 결과가 출력되었습니다.

 

두 연산의 결과가 다른 이유는 무엇이었을까요?

그 이유는 기본 자료형으로 선언한 경우 변수가 다르더라도 같은 내용(문자열)을 갖고 있다면 동일한 주소값을 가리키고 있기 때문입니다. 따라서 처음의 등위 연산자는 "같다" 는 결과를 출력하게 된 것 입니다.

 

이와 반대로 참조형의 경우에는 각각 메모리의 일정한 공간을 차지하기 때문에 기본 자료형과 같은 내용(문자열)을 갖고 있다 하더라도 다른 주소를 가리키게 됩니다. 그래서 다음의 등위 연산자는 "다르다" 는 결과를 나타내게 됩니다.

 

printResult(str3 == str4); // 다르다 

참조형 변수를 비교하더라고 마찬가지로 "다르다" 라는 결과를 얻게 될 것입니다.

 

결국 등위 연산자가 비교한 값은 실제 문자열이 아닌 문자열이 저장된 주소인 것이지요.

 

 

2. equals(), equalsIgnoreCase()

 

우리가 비교하고 싶은 것은 실제 문자열! 입니다.

 

1
2
3
4
// equals(), equalsIgnoreCase()
printResult(str2.equalsIgnoreCase(str3));    // 같다
printResult(str3.equalsIgnoreCase(str4));    // 같다
cs

 

그래서 문자열의 비교에는 String 클래스에서 제공해주는 equals(), equalsIgnoreCase() 메소드를 사용합니다. 실제 문자열을 비교하기 때문에 기본 자료형과 참조형의 비교에도 우리가 원하는 "같다" 는 결과를 제대로 돌려줍니다.

 

1
2
3
4
5
printResult("apple".equals("APPLE"));    // 다르다
printResult("apple".equals("apple"));    // 같다
        
printResult("apple".equalsIgnoreCase("APPLE"));    // 같다
printResult("apple".equalsIgnoreCase("apple")); // 같다
cs

 

equals() 메소드는 대소문자를 구분하여 비교하고

equalsIgnoreCase() 메소드는 대소문자를 구분하지 않고 비교하므로

원하는 비교 형태를 확인하시고 선택 / 사용하면 더욱 유용합니다.

 

 

3. 그 외의 방법들  : compareTo(), compareToIgnoreCase(), matches()

 

equals(), equalsIgnoreCase() 메소드 이외에도 

String 클래스에서 제공해주는 다양한 메소드를 활용할 수도 있습니다.

 

1
2
3
4
5
// compareTo(), compareToIgnoreCase()
printResult(str2.compareToIgnoreCase(str3) == 0);    // 같다
        
// matches(regex)
printResult(str2.matches(str3));    // 같다
cs

 

두 문자열의 길이가 같은지, 각각의 순서에 맞게 char 로 비교한 결과를 리턴하는

compareTo(), compareToIgnoreCase() 메소드는 두 문자열이 같다면 0 를 반환하게 됩니다.

 

또한 matches() 메소드는 파라미터로 정규식(regex) 를 입력받아, 문자열이 정규식과 일치하는지 확인하는 데 사용되지만 위에서와 같이 문자열 비교에도 이용할 수 있습니다.

 

Posted by maze1008
,

자바에서 정수를 표현하기 위해서 byte, short, int, long 등 다양한 타입이 지원됩니다.

 

그러나!  long 보다 큰 정수를 표현해야 할 때에는 어떻게 해야 할까요?

 

BigInteger 클래스는 이름 그대로 큰 정수값을 표현할 때 사용됩니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.math.BigInteger;
 
public class BigIntegerTest {
    public static void main(String[] args) {
        System.out.println("정수의 최대값 : " + Long.MAX_VALUE);
        System.out.println("정수의 최소값 : " + Long.MIN_VALUE);
        System.out.println();
 
        BigInteger bigValue1 = new BigInteger("10000000000000000000");
        BigInteger bigValue2 = new BigInteger("-9999999999999999999");
 
        BigInteger addResult = bigValue1.add(bigValue2);
        BigInteger mulRuslt = bigValue1.multiply(bigValue2);
        
        System.out.println("BigInteger 더하기 : " + addResult);
        System.out.println("BigInteger 곱하기 : " + mulRuslt);
    }
}
cs

 

<결과>

정수의 최대값 : 9223372036854775807
정수의 최소값 : -9223372036854775808

 

BigInteger 더하기 : 1
BigInteger 곱하기 : -99999999999999999990000000000000000000 

 

 

우선 정수의 최대값과 최소값을 확인하기 위해서 long 타입의 범위를 출력해 보았습니다.

 

그리고 이 범위를 벗어나는 아주 큰 정수들을 BigInteger 클래스를 사용하여 선언했습니다.

BigInteger  는 BigDecimal 과 마찬가지로 math 패키지에 포함되어 있으며, 일반적인 클래스를 사용하듯이 이용할 수 있습니다.

 

 

여기서 한가지 주의할 점은 생성자의 매개변수를 문자형으로 전달해야 된다는 것입니다.

문자형을 사용하는 이유는 아주 간단합니다. 숫자형으로 표현할 수 있는 범위를 벗어난 값이기 때문입니다!

BigInteger 클래스를 사용하는 이유이기도 하죠.

 

 

연산이 수행된 결과값이 보이시나요?

BigInteger 클래스에는 add, multiply 이외에 다양한 메소드들이 제공되고 있으니 정수 연산에 유용하게 이용할 수 있습니다.

 

 

 

'IT > Java' 카테고리의 다른 글

자바 랜덤함수(Java Random)  (0) 2015.03.24
자바 문자열 비교 - equals(), equalsIgnoreCase()  (0) 2015.03.17
BigDecimal 클래스 - 오차없이 실수 표현하기  (0) 2015.03.13
자바 버전 확인  (0) 2015.03.09
자바 환경변수 설정  (0) 2015.03.02

Posted by maze1008
,

실수형 데이터 타입을(float, double) 사용하여 값을 표현할 때에는 오차에 유의해야 합니다.

 

일반적인 프로그래밍에서 큰 영향이 없는 미묘한 차이일지라도 금융권 등에서는 치명적이 오류를 발생시키기 때문입니다.

 

자바의 BigDecimal 클래스을 사용하면 이러한 실수 표현의 문제점을 해결할 수 있습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.math.BigDecimal;
 
public class BigDecimalTest {
 
    public static void main(String[] args) {
        // test #1
        double value1 = 1.6;
        double value2 = 0.1;
        System.out.println("실수의 더하기 : " + (value1 + value2));
        System.out.println("실수의 곱하기 : " + (value1 * value2));
        System.out.println();
        
        // test #2
        BigDecimal value3 = new BigDecimal(1.6);
        BigDecimal value4 = new BigDecimal(0.1);
        System.out.println("BigDecimal 더하기 : " + value3.add(value4));    
        System.out.println("BigDecimal 곱하기 : " + value3.multiply(value4));    
        System.out.println();
        
        // test #3
        BigDecimal value5 = new BigDecimal("1.6");
        BigDecimal value6 = new BigDecimal("0.1");
        System.out.println("BigDecimal 더하기 : " + value5.add(value6));    
        System.out.println("BigDecimal 곱하기 : " + value5.multiply(value6));    
    }
}
cs

 

<결과>

실수의 더하기 : 1.7000000000000002
실수의 곱하기 : 0.16000000000000003

 

BigDecimal 더하기 : 1.7000000000000000943689570931383059360086917877197265625
BigDecimal 곱하기 : 0.1600000000000000177635683940025051398161724525855033823303533017413935457540219431393779814243316650390625

 

BigDecimal 더하기 : 1.7
BigDecimal 곱하기 : 0.16

 

 

1번째 테스트(test #1) 에서는 double 형 변수를 2개 생성하여 연산을 수행해 보았습니다.

예상된 결과는 더하기 : 1.7  곱하기 : 0.16 이지만 출력된 결과는 오차값을 표현하고 있습니다.

 

 

오차 문제를 해결하기 위해서 2번째 테스트(test #2) 에서 BigDecimal 클래스를 사용했습니다.

BigDecimal 은 math 패키지에 포함되어 있으며, 일반적인 클래스를 사용하듯이 new 키워드를 이용하여 객체를 생성한 후 add, multiply 메소드로 연산을 진행했습니다.

 

 

그런데 오차범위가 줄어들지 않고 오히려 더 상세하게 표현되고 있습니다!

BigDecimal 의 객체를 생성할 때 실수형 매개변수(1.6 과 0.1)가 전달되면서 이미 오차가 발생하기 때문에 더욱 심각한 연산 결과가 발생하게 되는 것입니다.

 

 

마지막으로 3번째 테스트(test #3) 에서는  BigDecimal 의 객체를 생성할 때 문자형 매개변수("1.6" 과 "0.1")가 전달되도록 작성해 보았습니다.

 

드디어 오차없이 정확한 결과값 1.7 과 0.16 이 출력되었습니다.

BigDecimal 클래스에는 add, multiply 이외에도 다양한 메소드가 제공되고 있으니 참고하시기 바랍니다.

 

 

 

Posted by maze1008
,

자바 버전 확인

IT/Java 2015. 3. 9. 01:00

윈도우에 설치된 자바의 버전을 확인하는 2 가지 방법에 대해 소개해 드리겠습니다.

 

1. 명령 프롬프트(터미널)에서 확인하기

 

개발자(프로그래머) 분들께서 일반적으로 사용하는 방법 입니다.

 

 

시작 메뉴를 클릭하여 cmd 를 입력후 Enter 버튼을 누릅니다.

 

 

 

명령 프롬프트(터미널) 에서 java -version 을 입력합니다.

화면에 자바 버전이 보여집니다. (제 컴퓨터에 설치된 버전은 1.7.0_25 입니다.)

 

 

 

2. 제어판에서 확인하기

 

명령 프롬프트를 자주 사용해보지 않으신 분들께서는 2번째 방법을 사용하셔도 같은 결과를 얻을 수 있습니다.

(명령 프롬프트는 개발자에게 익숙한 화면이므로, 일반 사용자분들께는 낯설게 느껴지실 겁니다.)

 

 

시작 메뉴를 클릭하여 제어판을 선택합니다.

 

 

 

프로그램을 클릭합니다.

 

 

 

Java 를 클릭합니다.

 

 

 

정보 버튼을 클릭합니다.

 

 

 

Java 정보 다이얼로그에 자바 버전이 보여집니다. (제 컴퓨터에 설치된 버전은 1.7.0_25-b17 입니다.)

 

1번째 방법보다 여러번의 클릭이 이루어져서 복잡해 보일 수 있지만

제어판 > 프로그램 > Java > 정보 > 버전확인 순서대로 따라오시면 쉽게 자바 버전 정보를 확인할 수 있습니다.

Posted by maze1008
,

자바 설치가 완료된 후에는 환경변수 설정이 필요합니다. 

(아직 JDK 다운로드 및 설치가 완료되지 않으셨다면 아래 페이지로 이동 후 설치를 완료하시기 바랍니다.)

자바 설치 - JDK 다운로드 및 설치방법 

 

 

자바 환경변수 설정은 시스템 어느 곳에서든지 자바 프로그램을 수행하기 위한 작업입니다.

지금부터 하나씩 설명 드리도록 하겠습니다.

 

 

 

JDK 가 설치된 경로를 확인합니다.

 

 

 

컴퓨터에서 오른쪽 마우스를 클릭하고 속성을 선택합니다.

 

 

 

고급 시스템 설정을 클릭합니다.

 

 

 

고급탭이 보여지고 환경 변수를 클릭합니다.

 

 

 

시스템 변수(S) 에서 변수 컬럼에 Path 를 선택하고 편집 버튼을 클릭합니다.

 

 

 

시스템 변수 편집 다이얼로그가 나타납니다.

변수 값 맨 마지막에 처음 확인했던 SDK 설치 경로를 추가합니다.

(Path 에는 이미 여러가지의 변수 값이 추가되어 있는 것을 확인하실 수 있습니다.

; 가 Separator 로 변수들이 구분되므로 아래와 같이 앞뒤로 ; 를 추가하여 SDK 설치 경로를 입력.

;C:\Program Files\Java\jdk1.7.0_13\bin;)

 

 

 

이제 환경변수가 제대로 설정되었는지 확인해 보도록 하겠습니다.

시작 메뉴를 클릭하여 cmd 를 입력후 Enter 버튼을 누릅니다.

 

 

 

command 다이얼로그에 javac 를 입력합니다.

화면과 같이 옵션값들이 보여지면 드디어 JDK 설치과정이 모두 완료된 것입니다.

이제 자바 프로그램 작성을 시작하십시오!!

 

 

Posted by maze1008
,

자바 설치를 한다는 것은 JDK 를 다운로드 받아 설치한다는 것을 의미합니다.

JDK (Java Development Kit) 는 자바 프로그램의 개발을 위한 소프트웨어와 라이브러리 모음입니다.

 

처음 자바를  접하시는 분들 또는 새로 JDK 설치가 필요하신 분들을 위해서

단계별로 상세하게 설명해 드리도록 하겠습니다.

 

 

 

1. JDK 다운로드

아래 링크를 통해서 Oracle 홈페이지를 방문하시면 JDK 를 무료로 다운 받을 수 있습니다.

http://www.oracle.com/ 

 

 

DOWNLOADS 에 마우스를 (클릭하지 마시고) 올려놓으시면 하위 메뉴들이 보여집니다.

그중에서 Java for Developers 를 클릭합니다.

 

 

 

일반적으로 자바 어플리케이션을 개발하기 위해 Java SE(Standard Edition) 가 사용됩니다.

현재 최신 버전인 7u13 을 다운받기 위해 위와 같이 클릭합니다.

 

 

 

License 와 관련하여 동의를 클릭하시고

리스트 중에서 자신의 컴퓨터 환경(OS)과 동일한 항목를 찾아서 Download 를 클릭합니다.

(저는 Windows7 32bit 환경이므로 Windows x86 의 jdk-7u13-windows-i586.exe 를 클릭하였습니다.)

 

 

 

브라우저 아래쪽으로 바로 실행 or 저장을 묻는 화면이 나타납니다.

실행을 선택합니다.

 

 

 

2. JDK 설치

 

 

설치여부를 묻는 다이얼로그입니다.

Next 버튼을 클릭합니다.

 

 

 

구체적인 설치요소 및 경로를  묻는 다이얼로그입니다.

Next 버튼을 클릭합니다.

* 설치요소

(1) Development Tools : 컴파일러 및 인터프리터를 포함한 각종 유틸리티와 라이브러리로 구성되는 개발환경

(2) Source code : J2SE 를 구성하는 여러 클래스의 소스코드

(3) Public JRE : 자바 프로그램 실행 환경인 J2SE Runtime

 

 

 

설치중 화면입니다.

 

 

 

설치 디렉토리 변경을 묻는 다이얼로그입니다.

Next 버튼을 클릭합니다.

 

 

 

설치가 완료되었습니다.

Close 버튼을 클릭합니다.

 

 

* 자바 설치가 완료된 후에는 환경변수 설정이 필요합니다.

아래 페이지로 이동 후 자바(Java) 환경변수 설정을 진행하시기 바랍니다.  

 자바 환경변수 설정

 

Posted by maze1008
,