주어진 숫자중 최소값을 찾아보기
주어진 숫자중 최소값을 찾아보기
우선 사람은 한눈에 보면 제일 최소값을 바로 찾을 수 있다.
하지만 잘 생각해보면, 머릿속에서 모든 숫자들을 파악하고 각각을 비교해 최소값을 찾는다.
이를 컴퓨터에게 설명하려면 어떻게 해야할까
A배열안에 값들이 들어있다고 가정하자.
내가 찾고싶은 값은 배열 안 숫자들중 최소값이기 때문에 최소값을 담아줄 변수를 선언해준다.
이 변수를 나중에 리턴하게된다.
int m;
숫자간의 크기를 비교하기때문에 모든 숫자들을 한번씩은 확인해봐야한다 따라서, for문으로 최소 한번이상은 루프를 돌아야한다.
for(int i=0; i<A.length(); i++){
}
숫자간의 비교를 통해 더 작은값을 찾아내고 변수 m에 값을 담아준다.
if(A[i] <= A[i+1]){
m = A[i];
}
(등호는 중복된 같은값이 나올 수도 있기 때문에 추가하였다.)
문제가 발생했다.
i+1은 루프끝부분에서 주어진 인덱스 범위를 초과하기 때문에 컴파일에러가 발생했다. 따라서 i+1은 사용하면 안된다.
그렇다면, 변수 m의 초기값을 A[0]로 두고, 루프시작을 A[1]부터 돌리게 하면 어떨까?
for(int i=1; i<A.length(); i++){
if(A[i] <= m){
m = A[i];
}
}
최소값을 문제없이 잘 구할 수 있다. 이제 함수로 만들면 된다.
public int getNumberMinimum(int[] A){
int m = A[i];
for(int i=1; i<A.length(); i++){
if(A[i] <= m){
m = A[i];
}
}
return m;
}
함수를 만들던 중, int[]만 받을 수 있는 것은 유연성이 부족하다고 느꼈다.
String[]로 입력을 받고 숫자타입이 아닌경우 NumberFormatException예외처리를 하고, 맞다면 숫자타입을 판별하여 해당 숫자를 리턴하는 함수를 만들어보겠다.
1. 모든 문자열배열이 숫자인지 판별
2. 문자열들의 숫자타입을 판별
3. 숫자타입에 맞는 함수를 호출
Character 클래스의 isDigit을 이용하면 for문 한번 더 돌려야하기때문에, 다른방법을 찾아보다가 정규식을 활용해보면 좋을것같다고 느꼈다.
모든 문자열을 검증해야하기때문에, else문을 넣어주어 하나라도 숫자타입이 아닌경우, return시키도록 하였다.
private boolean isNumeric(String[] strArr){
boolean isNumber = false;
for(String s : strArr){
if(s.matches("[+-]?\\d*(\\.\\d+)?")){
isNumber = true;
}else{
isNumber = false;
return isNumber;
}
}
return isNumber;
}
숫자임을 확인했으면, 어떤 숫자타입인지 구별하는 함수를 만들자.
1. 가장 큰 범위인 실수로 변환한다.
2. 정수로 변환했을때 값이 변하는지 변하지않는지 구별해 정수인지 판단한다.
3. 정수와 실수가 섞여있는 경우, 실수로 판단한다.
private int findNumberType(String[] strArr){
//기존상태는0, 1이면 정수, 2이면 실수
int flag = 0;
for(String s : strArr){
double d = Double.parseDouble(s);
if(d == (int) d){
flag = 1;
}else{
flag = 2;
return flag;
}
}
return flag;
}
최소값구하는 함수를 정수전용, 소수전용 각각만든다.
private int getIntMinimum(String[] strArr){
int[] intArr = new int[strArr.length()];
for(i=0; i<strArr.length(); i++){
intArr[i] = Int.parseint(strArr[i]);
}
Int m = intArr[0];
for(int i=1; i<intArr.length(); i++){
if(intArr[i] <= m){
m = intArr[i];
}
}
return m;
}
---
private double getDoubleMinimum(String[] strArr){
double[] doubleArr = new double[strArr.length()];
for(i=0; i<strArr.length(); i++){
doubleArr[i] = Double.parseDouble(strArr[i]);
}
double m = doubleArr[0];
for(double i=1; i<doubleArr.length(); i++){
if(doubleArr[i] <= m){
m = doubleArr[i];
}
}
return m;
}
이제 만들어놓은 함수들을 하나로 묶어 사용하기 편리하게 만들자. 문자열로 최소값을 변환하여 리턴하기로 했다.
public string getNumberMinimumToString(String[] strArr) throw NumberFormatException, IllegalArgumentException {
if(isNumeric(strArr)){
int flag = findNumberType(strArr);
switch(flag){
case 1: return String.valueOf(getIntMinimum(strArr));
case 2: return String.valueOf(getdoubleMinimum(strArr));
default :
throw new IllegalArgumentException("숫자타입이 올바르지 않습니다(정수 또는 소수가 아닙니다.)");
}
}else{
throw new NumberFormatException("숫자형식이 아닌 문자가 들어있습니다.");
}
}
나만의 클래스안에 만들어놓아 보관하면 될 것 같다.
내부적으로만 사용되는 함수들은 private으로 해두어야겠다.
현재는 정수, 실수만을 비교하지만,
문자가 들어오게되면 맨앞의 알파벳을 char타입으로바꾸어 아스키코드를 사용해 사전순으로 가장 앞에 있는 문자를 리턴하도록 만들 수도 있을 것 같다.
OCP원칙을 위반하지 않고 기능을 추가하기 위해서는 좀 더 결합도를 낮춘 코딩이 필요할 것 같다.
여기에는 디자인패턴을 사용하는게 맞을 것 같은데,
일단 오늘은 여기까지 하고 앞으로 여러가지 문제를 풀어보면서 디자인패턴도 공부하면서 적용해보면 재밌을 것 같다.