2012-04-02 28 views
6

我有double值,我想轉換到String值隨下列格式的限制位十進制數的雙精度值:格式使用最多五個總位數,四捨五入如果必要

number_of_fraction_digits = MAX(0, 5 - number_of_integer_digits)

本質上我想保留的位數爲5,如果可能的話,四捨五入小數位如有必要。例如:

 
float   String 
------------------------- 
    1    1 
    100    100 
100000   100000 
99999   99999 
99999.99  99999 
    9999.99   9999.9 
    999.99   999.99 
    23.34324  23.343 

我已經研究過使用DecimalFormat但據我可以告訴它並不完全做到我後。

它允許使用setMaximumFractionDigits()設置最大小數位數,但據我所知,我將不得不計算整數位數並自己執行上述計算。

所以基本的問題是,是否有一個很好的,乾淨的內置方式來格式化數字這種方式。

+0

我會說你截斷/切斷數字,而不是四捨五入。 – 2012-04-02 15:10:21

+0

是的,trucating數字會很好。 eee下面的答案非常接近,但'BigDecimal'在999.99的值處出現了一些奇怪的情況:將它舍入到了'999.98' – ulmangt 2012-04-02 15:19:14

+0

這是浮點數和雙精度數的精度有限造成的僞像。更高的精度,你會看到999.98999這是精確的,你可以用浮動。但是如果你砍掉最後3個9,你將以999.98結束。 – 2012-04-02 15:28:26

回答

6
public class SignificantFormat { 

    public static String formatSignificant(double value, int significant) 
    { 
     MathContext mathContext = new MathContext(significant, RoundingMode.DOWN); 
     BigDecimal bigDecimal = new BigDecimal(value, mathContext); 
     return bigDecimal.toPlainString(); 
    } 

    public static void main(String[] args) { 
     double[] data = { 1, 100, 100000, 99999, 99999.99, 9999.99, 999.99, 23.34324 }; 
     for(double d: data){ 
      System.out.printf("Input: %10s \tOutput: %10s\n", Double.toString(d), formatSignificant(d, 5)); 
     } 
    } 
} 
+0

有趣,很聰明。我之前沒有使用[MathContext](http://docs.oracle.com/javase/6/docs/api/index.html?java/math/MathContext.html)。 當我運行,除了例如一切看起來不錯: '輸入:999.99 \t輸出:999.98' 用'RoundingMode'四處玩,看看是否有一個簡單的解決有... – ulmangt 2012-04-02 15:11:05

+1

也許,這是一個實現由於MS Excel的ROUNDDOWN(999.99; 5)給出999,所以在MathContext中舍入算法的錯誤。99如你所期望的 – ecle 2012-04-02 15:17:55

+0

另外,要增加另一個不太正確的例子:'輸入:234.4 \t輸出:234.39'理想的情況是:'輸入:234.4 \t輸出:234.4' – ulmangt 2012-04-02 15:23:18

2

eee的答案更加清晰,並且幾乎可以一路獲得。但是,我確實要求數字位數(不包括可選小數點)始終小於給定數字(比如5)。

這包括任何領先的0.爲完全小數。

所以:

Input: 0.111111 Output: 0.11111

太長,需要進行:

Input: 0.111111 Output: 0.1111

這種方法是優雅的要少得多,但更具體的關於保障的最終長度字符串。

我已經在這裏發佈了它,因爲它可能是我解決問題的最終代碼,即使它不太優雅。

public static String format(double value, int totalDigits) 
{ 
    String s = String.valueOf(value); 
    int decimal = s.indexOf('.'); 

    // there is no decimal part, so simply return the String 
    if (decimal == -1) 
    { 
     return s; 
    } 
    else 
    { 
     int finalLength; 

     // example: 23.34324 
     // the final result will be length totalDigits + 1 because we will include the decimal 
     if (decimal < totalDigits) 
     { 
      finalLength = totalDigits + 1; 
     } 
     // example: 99999 
     // the final result will be length totalDigits because there will be no decimal 
     else if (decimal == totalDigits) 
     { 
      finalLength = totalDigits; 
     } 
     // example: 999999.999 
     // we can't make the final length totalDigits because the integer portion is too large 
     else 
     { 
      finalLength = decimal; 
     } 

     finalLength = Math.min(s.length(), finalLength); 

     return s.substring(0, finalLength); 
    } 
} 

public static void main(String[] args) 
{ 
    double[] data = { 1, 100, 1000, 10000, 100000, 99999, 99999.99, 9999.99, 999.99, 23.34324, 0.111111 }; 
    for (double d : data) 
    { 
     System.out.printf("Input: %10s \tOutput: %10s\n", Double.toString(d), format(d, 5)); 
    } 
} 
+0

你正在以良好的方式回答你自己的問題:)我認爲你可以去掉尾隨的零 – ecle 2012-04-02 17:00:34