2013-04-04 179 views
4

我知道這個問題是很多反覆,但請看看語句第一比馬克它已經回答了:)截斷雙精度到2位小數?

用於截斷雙重價值2位小數我使用的大多是隨處提到的兩個方面。下面

//this one 
    DecimalFormat dtime = new DecimalFormat("#.##"); 
    return Double.valueOf(dtime.format(val)); 
    //or the one below 
    BigDecimal bd = new BigDecimal(val); 
    BigDecimal rounded = bd.setScale(2, BigDecimal.ROUND_HALF_UP); 
    return rounded.doubleValue(); 

給他們的問題是,對於這兩種方式我主要是在數據集中獲得正確的四捨五入值。但奇怪的是,我同時獲得了2.00000000000005或19.97999999999這樣的值。

我沒有得到的問題是,爲什麼只有幾個值沒有被舍入。什麼可能是錯的?

+1

[浮點可能重複不準確](http://stackoverflow.com/questions/4575643/floating-point-inaccuracies) – Ingo 2013-04-04 18:31:49

+1

投票結束:你不明白關於雙精度/浮點精度的其他5786問題的答案。回去再讀一遍。 – Ingo 2013-04-04 18:32:42

+0

你會得到「價值如」2.00000000000005,或者你得到2.00000000000005?如果你得到19。例如,9800000000000004,這可能是由於將四捨五入的值轉換爲二進制浮點引起的。正如其他答案中所解釋的,這種轉換會導致一些錯誤。如果得到2.00000000000005,那麼還有一些其他問題,因爲已經舍入爲2.00的值在轉換爲浮點時將保持2。在後者情況下,Ingo以不正當的方式投票將其視爲重複。 – 2013-04-04 18:39:12

回答

2

爲了截斷double值2個小數位,我使用了兩種主要隨處可見的方法。

他們都是錯誤的,因爲他們正在嘗試不可能的事情。有沒有這樣的東西截斷雙精度到小數點後2位,因爲雙打不要有小數位。他們有二進制的地方。見my answer here作證明。如果您想要小數位,則必須使用小數基數,即BigDecimalDecimalFormat

+0

@mKorbel只爲你: - | – EJP 2013-04-05 00:05:09

0

問題是浮點數本質上是近似的,給定了基礎表示。因此,您需要在近似值較好的地方使用它們,並在近似值不好的地方避免使用它們(例如財務)。

rounded.doubleValue()的調用仍會返回一個浮點數,所以它仍受到表示限制的影響。

有關更多信息,請參見

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

+0

喜歡這個值..我的意思是小數位數不被截斷..抱歉的混淆 – Aneeque 2013-04-04 18:43:37

+0

瞭解。浮點表示沒有內置精度。當你「截斷」數字時,你只是將數字的某個部分清零,然後顯示剩下的部分。如果原來的數字沒有確切的浮點數表示,那麼您會被表示可以提供的最好數字卡住,數字與您提供的數字相似。例如。如果沒有19.98的精確浮點表示(使用你的例子),那麼你將不得不處理任何表示「足夠接近」。 – 2013-04-04 19:45:49

+0

thnx爲明確答案:)。任何方式來解決這個問題除了截斷爲一個字符串? – Aneeque 2013-04-04 20:28:27

-1

我是新來的,但保持在我面前的一切我是這樣做的。現在請注意,這是一個數學截斷,除了在每行之後的調試中,我不會將其轉換爲字符串。

這不是優雅,但似乎工作。這純粹是一個解決問題的框架。

無論如何;

import java.util.Scanner; 
public class TestConstructs 
{ 
private static double w; 
private static int w1; 
private static double w2; 
private static double w3; 
private static int w4; 
private static double w5; 
private static double w6; 

public static void main(String[] args) 
{ 
    // TODO Auto-generated method stub 
    TestConstructs foo = new TestConstructs(); 
    foo.setWage(w); 

} 

public void setWage(double w) 
{ 

    Scanner input = new Scanner(System.in); 
    System.out.println("Enter Wage: "); //enter something longish like 30987.978654 or w/e 
    w = input.nextDouble(); 
    w1 = (int)w; 
    System.out.printf("%d w1\n",w1); 
    w2 = w - w1; 
    System.out.printf("%.3f w2\n",w2); 
    w3 = w2*100; 
    System.out.printf("%.3f w3\n",w3); 
    w4 = (int)w3; 
    System.out.printf("%d w4\n",w4); 
    w5 = (double)w4; 
    System.out.printf("%.3f w5\n",w5); 
    w6 = 0 + w5/100; 
    System.out.printf("%.3f w6\n",w6); 
    w = w1 + w6; 

    System.out.printf("%.3f final value\n",w); //.3 to show zero 
    input.close(); 
} 

} 

我在最後 有什麼輸入工資: 30987.978654 30987 W1 0.979 W2 97.865 W3 97 W4 97.000 W5 0.970 W6 30987.970終值

+0

它不起作用。看到我的答案在http://stackoverflow.com/questions/153724/how-to-round-a-number-to-n-decimal-places-in-java作證明。 – EJP 2013-09-29 20:29:04

+0

雖然這樣做你的方式做了這個項目圓了,我不得不將TRUNCATE兩位小數,而不是圓。另外,在我參加的課程中,我無法使用超出課程範圍的方法。 – user2829229 2013-09-29 22:02:29

+0

在另一個筆記我知道雙打不綁定的地方,所以沒有絕對截斷沒有字符串轉換。這樣做的目的是儘可能多地丟棄數字垃圾到第二個小數點以外,double中的任何內容都不是精確的,但是使用我寫的有效地破壞了位置.00(x)處整數的考慮,這正是我所需要的。 – user2829229 2013-09-29 22:07:15