생각보다는 질문의 내용을 구현하기가 좀 까다롭네요. 겨우 동작하는 버전을 한번 만들어 봤는데, 퍼포먼스나 코드의 복잡도 상으로는 많은 부분 개선되어야할 것 같네요.
private String makeString(int original, double ratio, int wantSize) {
BigDecimal src = BigDecimal.valueOf(original * ratio); //eg. 1 * 0.003
// 해당 숫자를 원하는 자리수 만큼 자르려면 소수점 몇자리를 사용해야 하는지 구한다.
int scale = getDesiredScale(src, wantSize);
// 위에 구한 소수점 자리수를 갖는 BigDecimal로 만든다.
BigDecimal value = src.setScale(scale, BigDecimal.ROUND_FLOOR);
// 정수값
int intValue = value.intValue();
// 소수점이 필요없는 최소값을 구한다.
// 예를 들어, 앞에서 4자리를 자른다면, 10000이 소수점이 필요없는 최소값이 되고 10000보다 작은 숫자는
// 무조건 소수점이 생기게 된다.
int boundaryValue = (int) Math.pow(10, wantSize);
// 자르려고하는 최소숫자보다 작으면 여기서 리턴.
if (intValue < boundaryValue) {
// 문자열이 아니라 숫자 타입을 리턴하고 싶으면 리턴타입을 BigDecimal로 바꾸고 value를 리턴.
return value.toString();
}
// 정수값이 자르려고 한 숫자보다 크게 나오면, 예를 들면, 37037.034 -> 37037 > 10000
final String s = String.valueOf(intValue);
// 정수값의 길이만큼 '0'를 뒷쪽에 붙인다. eg. 37037 -> 37030
return StringUtils.padRight(s.substring(0, wantSize), s.length(), '0');
}
전체 메소드는 위와 같습니다.
private int getDesiredScale(BigDecimal src, int maxScale) {
BigDecimal comparison = BigDecimal.TEN;
int scale = 0;
while (scale++ < maxScale && src.compareTo(comparison) > 0) {
comparison = comparison.multiply(BigDecimal.TEN);
}
return maxScale - scale;
}
public class StringUtils {
public static String padRight(String src, int strLength, char padChar) {
if (src == null || src.length() > strLength) {
return src;
}
String paddedStr = "";
int padSize = strLength - src.length();
for (int i = 0 ; i < padSize; i++) {
paddedStr += padChar;
}
return src + paddedStr;
}
}
제코드는 겨우 동작하는 최적화된 코드가 아니니, 참고만 하시고 최적화하신 다음 사용하기를 강력 권장합니다. 아이디어만 가져가세요. 코드에 주석도 많이 달았고, 이제 남은 몫은 님의 것이니 제코드 관련해서는 더는 질문은 받지 않겠습니다.