자바에서는 Integer.valueOf, Integer.parseInt와 같은 형변환 기능을 지원하는데요. 해당 기능들을 사용하지 않고 구현을 할 예정입니다.
private int getInt(String line) {
final char c = line.charAt(0);
final int len = line.length();
int total = 0, pow = 1;
for (byte i = 1; i<len+(c == '-' || c == '+' ? 0 : 1); i++) {
total += pow * ((byte) (line.charAt(len-i)) - 48);
pow *= 10;
}
return c == '-' ? -total : total;
}
동작 원리는 간단한데 문자열 1개씩 읽어가면서 계산해나아가는 원리입니다.
String -> char -> int
예시로 "12345" => 10000 + 2000 + 300 + 40 + 5 => 12345
와 같은 과정을 통해 정수형으로 변환을 합니다.
System.out.println(getInt("15") - getInt("5")); // 15 - 5
System.out.println(getInt("15") - getInt("-5")); // 15 - (-5)
System.out.println(getInt("15") + getInt("5")); // 15 + 5
System.out.println(getInt("15") + getInt("+5")); // 15 + (+5)
출력
10
20
20
20
동작 원리는 정수형과 유사하지만 소수점만 따로 분리해서 계산을 합니다.
소수점의 위치를 구하고 마지막에 위치 많큼 나누어주면 됩니다.
예시로 "3.14" => (정수형 방식) => 314 / 100 => 3.14
과 같은 방식으로 실수형을 구현하였습니다.
private float getFloat(String line) {
final char c = line.charAt(0);
final int len = line.length();
int total = 0, pow = 1;
float pos = 0;
for (byte i = 1; i<len+(c == '-' || c == '+' ? 0 : 1); i++) {
char l = line.charAt(len-i);
if (l == '.') pos = pow;
else {
total += pow * ((byte) l - 48);
pow *= 10;
}
}
return c == '-' ? -(total / pos) : total / pos;
}
System.out.println(getFloat("3.14") - getFloat("0.14")); // 3.14 - 0.14
System.out.println(getFloat("3.14") - getFloat("-0.14")); // 3.14 - (-0.14)
System.out.println(getFloat("3.14") + getFloat("0.06")); // 3.14 + 0.06
System.out.println(getFloat("3.14") + getFloat("-0.06")); // 3.14 + (-0.06)
출력
3.0
3.2800002
3.2
3.0800002
부동 소수점 땜에 저렇게 나온다..(Float이라서 7자리까지만)
System.out.println(3.14 - (-0.14));
출력
3.2800000000000002
그냥 써도 심각하게 나온다.
숫자로만 이루어진 문자열이 들어와야한다는 양심적인(?) 값이 들어와야지 재대로 된 값이 출력된다는 단점이 있다.
사실 중간에 숫자 확인해주는 로직을 구현해도 되지만 귀찮다.
소수점 계산에 정확도가 떨어진다.
소수점은 그냥 계산해도 정확도가 높은 편은 아니라서... 정확도를 높히고 싶다면 BigDecimal를 사용하는 것도 방법일 듯하다.
그냥 Integer.parseInt(), Float.parseFloat() 쓰는게 좋을지도...?