사용자 도구

사이트 도구


java:number

Java Number

숫자들 간의 Type 무시 비교 / Comparing numbers

public int compare(final Number x, final Number y) {
    if(isSpecial(x) || isSpecial(y)) {
        return Double.compare(x.doubleValue(), y.doubleValue());
    } else {
        // x, y의 class가 동일하다면 y.compareTo(y) 만하도록 처리하면 성능이 좋아질 수 있다.
        // x, y의 class가 다를 경우에만 BigDecimal로 변환한다.
        return toBigDecimal(x).compareTo(toBigDecimal(y));
    }
}
 
private static boolean isSpecial(final Number x) {
    boolean specialDouble = x instanceof Double
            && (Double.isNaN((Double) x) || Double.isInfinite((Double) x));
    boolean specialFloat = x instanceof Float
            && (Float.isNaN((Float) x) || Float.isInfinite((Float) x));
    return specialDouble || specialFloat;
}
 
private static BigDecimal toBigDecimal(final Number number) {
    if(number instanceof BigDecimal)
        return (BigDecimal) number;
    if(number instanceof BigInteger)
        return new BigDecimal((BigInteger) number);
    if(number instanceof Byte || number instanceof Short
            || number instanceof Integer || number instanceof Long)
        return new BigDecimal(number.longValue());
    if(number instanceof Float || number instanceof Double)
        // float,double은 toString을 통해 변환하는 것이 정확도가 더 높았다.
        return new BigDecimal(number.toString());
 
    try {
        return new BigDecimal(number.toString());
    } catch(final NumberFormatException e) {
        throw new RuntimeException("The given number (\"" + number
                + "\" of class " + number.getClass().getName()
                + ") does not have a parsable string representation", e);
    }
}
  • isSpecial이 없으면 FloatDouble의 NaN, infinite 상태에서 NumberFormatException이 발생한다.
  • 비교 대상이 되는 두 객체가 동일 클래스 인스턴스라면 BigDecimal로 변환하지 말고 즉시 비교하고 리턴하는 코드를 추가할 것. 그러면 불필요한 객체 생성 변환이 없어 성능향상이 될 것으로 보인다.
  • 특수한 숫자 객체를 제외한 int 계열의 숫자는 바로 BigDecimal로 변환한다.

Hex 16진수

  • 숫자를 16진수로 바꾸기
  • Long.toHexString() 같은 메소드를 사용하면 된다. Integer 등에도 존재함.
  • 그러나 hex는 보통 2자리씩 이뤄지는데 때로 앞자리가 0으로 시작하면 홀수자리 hex 문자열이 나올 수도 있다. 이때, String.format()을 사용한다. Integer to two digits hex in Java
// Long 값을 16자리 Hex 문자열로
String hex = String.format("%016x", value);
import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(someByteArray));
  • 순수 Java
byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61};
String hex = javax.xml.bind.DatatypeConverter.printHexBinary(bytes);
  • 순수 Java - Java 8 이전
public static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars);
}
  • 순수 Java - Java 9 이후
public static String bytesToHex(byte[] bytes) {
    byte[] hexChars = new byte[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars, StandardCharsets.UTF_8);
}
java/number.txt · 마지막으로 수정됨: 2021/02/17 00:09 저자 kwon37xi