%, ^ , sqrt(a) Log(a), sin(a), cos(a), ten(a) 추가
수식 전체 입력 가능
while(true){
System.out.println("수식을 입력하세요");
System.out.println("ex) a (+, -, *, /, %, ^) b");
System.out.print("ex) sqrt(a), sin(a), tan(a), cos(a), log(a)\n: ");
String input = sc.nextLine();
parsed = parseExpression(input);
if(parsed != null){
break;
} // 오타 예외 처리
System.out.println("잘못된 값을 입력하였습니다.");
}
if(isUnaryOperator(parsed[0])) {
operatortype = OperatorType.getOperatorType(parsed[0].charAt(0)); // 한 글자로 변환된 값 사용
fstVal = getData(parsed[1]);
sndVal = null;
} else {
fstVal = getData(parsed[0]);
operatortype = OperatorType.getOperatorType(parsed[1].charAt(0));
sndVal = getData(parsed[2]);
}
public static String[] parseExpression(String input){
input = input.replace(" ",""); // 공백 제거
if(input.startsWith("sqrt(") && input.endsWith(")")){
return new String[]{"qrt", input.substring(5, input.length() - 1)};
} else if (input.startsWith("log(") && input.endsWith(")")) {
return new String[]{"log", input.substring(4, input.length() - 1)};
} else if (input.startsWith("sin(") && input.endsWith(")")) {
return new String[]{"sin", input.substring(4, input.length() - 1)};
} else if (input.startsWith("cos(") && input.endsWith(")")) {
return new String[]{"cos", input.substring(4, input.length() - 1)};
} else if (input.startsWith("tan(") && input.endsWith(")")) {
return new String[]{"tan", input.substring(4, input.length() - 1)};
}
Pattern pattern = Pattern.compile("(\\d+(?:\\.\\d+)?)([+\\-*/^%])(\\d+(?:\\.\\d+)?)"); //정규 표현식(소수점 허용)
Matcher matcher = pattern.matcher(input);
if(matcher.matches()){
return new String[]{matcher.group(1), matcher.group(2), matcher.group(3)};
} else{
return null;
}
}
if(operator.monomial()){
String simBol = "";
switch (operator){
case sqrt:
result = Math.sqrt(fstValDouble);
simBol = "sqrt";
break;
case log:
if (fstValDouble <= 0) {
throw new IllegalArgumentException("로그 값은 0보다 커야 합니다.");
}
result = Math.log(fstValDouble);
simBol = "log";
break;
case sin:
result = Math.sin(Math.toRadians(fstValDouble));
simBol = "sin";
break;
case cos:
result = Math.cos(Math.toRadians(fstValDouble));
simBol = "cos";
break;
case tan:
result = Math.tan(Math.toRadians(fstValDouble));
simBol = "tan";
break;
}
sqrt와 sin의 충돌OperatorType.getOperatorType('s')를 호출하였을 때, sin과 sqrt가 충돌하여 sin으로만 인식
public enum OperatorType {
add('+'), sub('-'), mul('*'), div('/'),
pow('^'), mod('%'),
log('l'), sin('s'), cos('c'), tan('t'), sqrt('s'); // ← sqrt와 sin이 같은 's'
}
if(isUnaryOperator(parsed[0])) {
operatortype = OperatorType.getOperatorType(parsed[0].charAt(0)); // ← 앞글자 하나만 사용!
}
문제 원인
앞글자 하나만 사용함으로 sqrt와 sin모두 s 전달
문제 해결
enum에서 sqrt의 심볼을 q로 변경parseExpression()에서 qrt로 변경결과
sin -> s , sqrt -> q로 인식하여 충돌 해결
회고 및 개선
enum에서 OperatorType를 정의 할때 단어의 첫 글자가 겹치지 않도록 설계하는것이 중요char 매핑이 겹치지 않도록 설계charAt(0)을 사용하면 연산자 구분이 어려움으로, 문자열 기반으로 처리하는것이 편함