tofixed - java除法小數點




如何在Java中將數字四捨五入到小數點後n位 (20)

我想要的是將double轉換為使用half-up方法進行舍入的字符串的方法 - 即如果小數點要捨入為5,則它總是向上舍入到前一個數字。 這是大多數人在大多數情況下期望的四捨五入標準方法。

我也只想顯示有效數字 - 即不應該有任何尾隨零。

我知道這樣做的一種方法是使用String.format方法:

String.format("%.5g%n", 0.912385);

收益:

0.91239

這很棒,但它總是顯示5位小數的數字,即使它們不顯著:

String.format("%.5g%n", 0.912300);

收益:

0.91230

另一種方法是使用DecimalFormatter

DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);

收益:

0.91238

但是,正如你所看到的,這使用半雙舍入。 如果前面的數字是偶數,那麼它會下降。 我想要的是這樣的:

0.912385 -> 0.91239
0.912300 -> 0.9123

在Java中實現這個最好的方法是什麼?


@Milhous:舍入的十進制格式非常好:

你也可以使用

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

以確保你有尾隨0。

我想補充一點,這種方法非常擅長提供實際的數字舍入機制 - 不僅在視覺上,而且在處理時。

假設:您必須在GUI程序中實施捨入機制。 要改變結果輸出的準確性/精確度,只需更改插入符號格式(即在括號內)。 以便:

DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);

將作為輸出返回: 0.912385

DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);

將作為輸出返回: 0.91239

DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);

將作為輸出返回: 0.9124

[編輯:如果插入符格式如此(“#0。############”),並且為參數輸入了小數,例如3.1415926,則DecimalFormat不會產生任何垃圾例如追踪零),並將返回: 3.1415926 ..如果你是這樣傾斜。 當然,對於某些開發人員的喜好有點冗長 - 但是,嘿,它在處理過程中佔用的內存很少,並且很容易實現。]

基本上,DecimalFormat的美妙之處在於它同時處理字符串外觀 - 以及舍入精度集合的級別。 Ergo:對於一個代碼實現的價格你會得到兩個好處。 ;)


DecimalFormat是輸出的最佳方式,但我不喜歡它。 我總是這樣做,因為它會返回雙倍的價值。 所以我可以使用它不僅僅是輸出。

Math.round(selfEvaluate*100000d.0)/100000d.0;

要么

Math.round(selfEvaluate*100000d.0)*0.00000d1;

如果您需要較大的小數位值,則可以使用BigDecimal。 無論如何.0是重要的。 沒有它,0.33333d5的捨入返回0.33333,只允許9位數字。 沒有.0的第二個函數有0.30000返回0.30000000000000004的問題。


If you Consider 5 or n number of decimal. May be this answer solve your prob.

    double a = 123.00449;
    double roundOff1 = Math.round(a*10000)/10000.00;
    double roundOff2 = Math.round(roundOff1*1000)/1000.00;
    double roundOff = Math.round(roundOff2*100)/100.00;

    System.out.println("result:"+roundOff);

Output will be: 123.0 1
this can be solve with loop and recursive function.


If you're using a technology that has a minimal JDK. Here's a way without any Java libs:

double scale = 100000;    
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;

To achieve this we can use this formatter:

 DecimalFormat df = new DecimalFormat("#.00");
 String resultado = df.format(valor)

要么:

DecimalFormat df = new DecimalFormat("0.00"); :

Use this method to get always two decimals:

   private static String getTwoDecimals(double value){
      DecimalFormat df = new DecimalFormat("0.00"); 
      return df.format(value);
    }

Defining this values:

91.32
5.22
11.5
1.2
2.6

Using the method we can get this results:

91.32
5.22
11.50
1.20
2.60

demo online.


下面的代碼片段顯示瞭如何顯示n個數字。 訣竅是將變量pp設置為1,然後設置n個零。 在下面的例子中,變量pp值有5個零,所以會顯示5位數字。

double pp = 10000;

double myVal = 22.268699999999967;
String needVal = "22.2687";

double i = (5.0/pp);

String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();

你也可以使用

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

以確保你有尾隨0。



假設valuedouble ,你可以這樣做:

(double)Math.round(value * 100000d) / 100000d

這是5位數字的精度。 零的數量表示小數位數。


假設你有

double d = 9232.129394d;

你可以使用BigDecimal

BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();

或沒有BigDecimal

d = Math.round(d*100)/100.0d;

與這兩個解決方案d == 9232.13


如果你想得到結果作為字符串,下面是你可以使用的一個總結:

  1. DecimalFormat#setRoundingMode()

    DecimalFormat df = new DecimalFormat("#.#####");
    df.setRoundingMode(RoundingMode.HALF_UP);
    String str1 = df.format(0.912385)); // 0.91239
    
  2. BigDecimal#setScale()

    String str2 = new BigDecimal(0.912385)
        .setScale(5, BigDecimal.ROUND_HALF_UP)
        .toString();
    

如果你想要double的結果,這裡有一個你可以使用的庫的建議。 但我不會推薦它用於字符串轉換,因為double可能無法完全表示您想要的內容(請參閱here ):

  1. 來自Apache Commons Math的Precision

    double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
    
  2. Colt的Functions

    double rounded = Functions.round(0.00001).apply(0.912385)
    
  3. 來自Weka的Utils

    double rounded = Utils.roundDouble(0.912385, 5)
    

如果您使用DecimalFormatdouble轉換為String ,則非常簡單:

DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);

double num = 1.234567;
return formatter.format(num);

有幾種RoundingMode枚舉值可供選擇,具體取決於您所需的行為。


您可以使用DecimalFormat類。

double d = 3.76628729;

DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal =  Double.valueOf(newFormat.format(d));

您可以使用以下實用程序方法 -

public static double round(double valueToRound, int numberOfDecimalPlaces)
{
    double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
    double interestedInZeroDPs = valueToRound * multipicationFactor;
    return Math.round(interestedInZeroDPs) / multipicationFactor;
}

我同意使用DecimalFormat ---或者BigDecimal

請先閱讀以下更新

但是,如果您確實想要捨入double值並獲得double值結果,則可以使用上面提到的org.apache.commons.math3.util.Precision.round(..) 該實現使用BigDecimal ,很慢並且會產生垃圾。

DoubleRounder實用程序在decimal4j庫中提供了類似但快速且無垃圾的方法:

 double a = DoubleRounder.round(2.0/3.0, 3);
 double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
 double c = DoubleRounder.round(1000.0d, 17);
 double d = DoubleRounder.round(90080070060.1d, 9);
 System.out.println(a);
 System.out.println(b);
 System.out.println(c);
 System.out.println(d);

會輸出

 0.667
 0.666
 1000.0
 9.00800700601E10

請參閱https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility

免責聲明:我參與了decimal4j項目。

更新:正如@iaforek指出的,DoubleRounder有時會返回違反直覺的結果。 原因是它執行數學正確的四捨五入。 例如DoubleRounder.round(256.025d, 2)將舍入到256.02,因為表示為256.025d的double值略小於理性值256.025,因此將向下舍入。

筆記:

  • 此行為與BigDecimal(double)構造函數非常相似(但不包含使用字符串構造函數的valueOf(double) )。
  • 這個問題可以通過一個雙舍入步驟來避免,首先是更高的精度,但這很複雜,我不打算在這裡詳細討論

由於這些原因和上面提到的所有內容,我不能推薦使用DoubleRounder


正如其他人已經註意到的,正確的答案是使用DecimalFormatBigDecimal 。 浮點沒有小數位,所以你不可能在第一個地方舍入/截斷它們的特定數目。 你必須使用十進制基數,這就是這兩個類所做的。

我將以下代碼作為反向示例發佈到此線程中的所有答案,並且實際上遍及(和其他地方)推薦的乘法,接著是截斷,然後是除法。 這種技術的倡導者有義務解釋為什麼下面的代碼在超過92%的情況下產生了錯誤的輸出。

public class RoundingCounterExample
{

    static float roundOff(float x, int position)
    {
        float a = x;
        double temp = Math.pow(10.0, position);
        a *= temp;
        a = Math.round(a);
        return (a / (float)temp);
    }

    public static void main(String[] args)
    {
        float a = roundOff(0.0009434f,3);
        System.out.println("a="+a+" (a % .001)="+(a % 0.001));
        int count = 0, errors = 0;
        for (double x = 0.0; x < 1; x += 0.0001)
        {
            count++;
            double d = x;
            int scale = 2;
            double factor = Math.pow(10, scale);
            d = Math.round(d * factor) / factor;
            if ((d % 0.01) != 0.0)
            {
                System.out.println(d + " " + (d % 0.01));
                errors++;
            }
        }
        System.out.println(count + " trials " + errors + " errors");
    }
}

這個程序的輸出:

10001 trials 9251 errors

編輯:為了解決下面的一些註釋,我使用BigDecimal測試循環的模數部分和模數運算的new MathContext(16) ,如下所示:

public static void main(String[] args)
{
    int count = 0, errors = 0;
    int scale = 2;
    double factor = Math.pow(10, scale);
    MathContext mc = new MathContext(16, RoundingMode.DOWN);
    for (double x = 0.0; x < 1; x += 0.0001)
    {
        count++;
        double d = x;
        d = Math.round(d * factor) / factor;
        BigDecimal bd = new BigDecimal(d, mc);
        bd = bd.remainder(new BigDecimal("0.01"), mc);
        if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
        {
            System.out.println(d + " " + bd);
            errors++;
        }
    }
    System.out.println(count + " trials " + errors + " errors");
}

結果:

10001 trials 4401 errors

試試這個:org.apache.commons.math3.util.Precision.round(double x,int scale)

請參閱: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html : http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html

Apache Commons數學圖書館主頁是: http://commons.apache.org/proper/commons-math/index.html : http://commons.apache.org/proper/commons-math/index.html

這種方法的內部實現是:

public static double round(double x, int scale) {
    return round(x, scale, BigDecimal.ROUND_HALF_UP);
}

public static double round(double x, int scale, int roundingMethod) {
    try {
        return (new BigDecimal
               (Double.toString(x))
               .setScale(scale, roundingMethod))
               .doubleValue();
    } catch (NumberFormatException ex) {
        if (Double.isInfinite(x)) {
            return x;
        } else {
            return Double.NaN;
        }
    }
}

請記住,String.format()和DecimalFormat會使用默認的Locale生成字符串。 因此,他們可能會使用點或逗號作為整數和小數部分之間的分隔符來編寫格式化數字。 要確保四捨五入的字符串是你想要使用java.text.NumberFormat的格式:

  Locale locale = Locale.ENGLISH;
  NumberFormat nf = NumberFormat.getNumberInstance(locale);
  // for trailing zeros:
  nf.setMinimumFractionDigits(2);
  // round to 2 digits:
  nf.setMaximumFractionDigits(2);

  System.out.println(nf.format(.99));
  System.out.println(nf.format(123.567));
  System.out.println(nf.format(123.0));

Will print in English locale (no matter what your locale is): 0.99 123.57 123.00

The example is taken from Farenda - how to convert double to String correctly .


DecimalFormat myFormatter = new DecimalFormat("0.000");
String output = myFormatter.format(2.34d);

double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;




digits