자바 에서 부동 소수점 의 빠 르 고 간단 한 포맷 을 실현 합 니 다.

최근 회사 의 시스템 조정 에서 double 형식의 데 이 터 를 문자열 연산 으로 포맷 하여 많은 CPU 시간 을 차지 하 는 것 을 발견 하 였 다.
코드 에서 사용 하 는 포맷 도 구 는 NumberFormat 입 니 다.일반적인 사용 방식 은:
NumberFormat f = NumberFormat.getNumberInstance();
...
f.format(value);

double 에 대해 서 는 DecimalFormat 인 스 턴 스 로 처리 합 니 다.기본 값 은 3 비트 소 수 를 유지 하고 나머지 0 을 삭제 합 니 다.
원래 포맷 은 너무 많은 계산 을 소모 하지 않 아 도 되 지만 DecimalFormat 은 유 니 버 설 성과 동기 화 처 리 를 고려 해 야 하기 때문에 성능 손실 이 많다.JDK 7 의 java.text.decimalFormat 의 원본 코드 를 참조 할 수 있 습 니 다)
따라서 간단 하고 빠 른 형식 도구,장점 을 스스로 실현 합 니 다.
  • DecimalFormat 보다 성능 이 적어도 한 배 좋 은 효 과 를 얻 을 수 있 습 니 다

  • 4.567917.그리고 정밀도 가 잃 어 버 리 지 않 습 니 다
    한계 성:
    4.567917.풍부 한 포맷 모드 를 제공 하지 않 고 더 블 을 읽 을 수 있 는 가장 짧 은 문자열 로 바 꿉 니 다
    포맷 예:
    3.145926---->(4 자리 소수 후의 문자 유지)3.1459
    3.224450--->(4 자리 소수 후의 문자 유지)3.2245,주석:DecimalFormat 은 3.2244 로 포맷 됩 니 다!
    1.999964->(4 자리 소수 후의 문자 유지)2
    0---->(4 자리 소수 뒤의 문자 유지)0
    관련 도구:
  • 주로 Math 도구 류 의 abs,nextUp,pow 등 함수(JDK 1.6 이후 Math 도구 자체 도 성능 개선)
  • 초대형 데이터 나 초고 정밀도 에 대해 BigDecimal 처리 로 전환 합 니 다(이때 성능 은 DecimalFormat 과 동일 합 니 다)

  • 4.567917.문자열 작업 을 char[]배열 로 바 꾸 어 작업 의 성능 을 향상 시 킵 니 다
    성능 테스트 결과:
    환경:Win 7 64 비트 i5-3320 8G 메모리 JDK7u 40
    Precision-0 and Loop times-1000000:
    NumberFormat time cost(ms): 884
    Fast Format time cost(ms):  188
    BigDecimal time cost(ms): 482
    Precision-1 and Loop times-1000000:
    NumberFormat time cost(ms): 727
    Fast Format time cost(ms):  180
    BigDecimal time cost(ms): 485
    Precision-2 and Loop times-1000000:
    NumberFormat time cost(ms): 473
    Fast Format time cost(ms):  164
    BigDecimal time cost(ms): 516
    Precision-3 and Loop times-1000000:
    NumberFormat time cost(ms): 509
    Fast Format time cost(ms):  157
    BigDecimal time cost(ms): 487
    Precision-4 and Loop times-1000000:
    NumberFormat time cost(ms): 521
    Fast Format time cost(ms):  159
    BigDecimal time cost(ms): 480
    원본 코드:
    	private final static char[][] LEADING_DECIMALS = new char[][] { "0.".toCharArray(), "0.0".toCharArray(),
    			"0.00".toCharArray(), "0.000".toCharArray(), "0.0000".toCharArray(), "0.00000".toCharArray(),
    			"0.000000".toCharArray(), "0.0000000".toCharArray(), "0.00000000".toCharArray(),
    			"0.000000000".toCharArray(), "0.0000000000".toCharArray(), "0.00000000000".toCharArray(),
    			"0.000000000000".toCharArray(), "0.0000000000000".toCharArray(), "0.00000000000000".toCharArray(),
    			"0.000000000000000".toCharArray() };
    
    	/**
    	 *        double,    (   )<br>
    	 *    :<br>
    	 * NumberFormat f = NumberFormat.getNumberInstance();<br>
    	 * f.setGroupingUsed(false);<br>
    	 * f.setMaximumFractionDigits(precision);<br>
    	 * f.format(d);<br>
    	 *          NumberFormat  ,      。<br>
    	 * 
    	 * @param d
    	 *            the double value
    	 * @param precision
    	 *            [0,16]
    	 * @return
    	 * @see NumberFormat
    	 */
    	public static String fastFormat(double d, int precision) {
    		int posPrecision = Math.abs(precision);
    		double roundUpVal = Math.abs(d) * Math.pow(10d, posPrecision) + 0.5d;
    		if (roundUpVal > 999999999999999d || posPrecision > 16) {// double has max 16 precisions
    			return bigDecFormat(d, posPrecision);
    		}
    		long longPart = (long) Math.nextUp(roundUpVal);
    		if (longPart < 1) {
    			return "0";
    		}
    		char[] longPartChars = Long.toString(longPart).toCharArray();
    		char[] formatChars = null;
    		if (longPartChars.length > posPrecision) {
    			int end = longPartChars.length - 1;
    			int decIndex = longPartChars.length - posPrecision;
    			while (end >= decIndex && longPartChars[end] == '0') {
    				end--;
    			}
    			if (end >= decIndex) {
    				formatChars = new char[end + 2];
    				System.arraycopy(longPartChars, 0, formatChars, 0, decIndex);
    				formatChars[decIndex] = '.';
    				System.arraycopy(longPartChars, decIndex, formatChars, decIndex + 1, end - decIndex + 1);
    			} else {
    				formatChars = new char[decIndex];
    				System.arraycopy(longPartChars, 0, formatChars, 0, decIndex);
    			}
    		} else {
    			int end = longPartChars.length - 1;
    			while (end >= 0 && longPartChars[end] == '0') {
    				end--;
    			}
    			char[] leadings = LEADING_DECIMALS[posPrecision - longPartChars.length];
    			formatChars = Arrays.copyOf(leadings, leadings.length + end + 1);
    			System.arraycopy(longPartChars, 0, formatChars, leadings.length, end + 1);
    		}
    		return Math.signum(d) > 0 ? new String(formatChars) : "-" + new String(formatChars);
    	}
    
    	private static String bigDecFormat(double d, int precision) {
    		String formatStr = new BigDecimal(Double.toString(d)).setScale(Math.abs(precision), RoundingMode.HALF_UP)
    				.toString();
    		if (precision == 0) {
    			return formatStr;
    		}
    		int end = formatStr.length() - 1;
    		while (end >= 0 && formatStr.charAt(end) == '0') {
    			end--;
    		}
    		formatStr = formatStr.substring(0, end + 1);
    		if (formatStr.charAt(formatStr.length() - 1) == '.') {
    			formatStr = formatStr.substring(0, formatStr.length() - 1);
    		}
    		return formatStr;
    	}
    
    

    좋은 웹페이지 즐겨찾기