2013-07-09 140 views
0

我做了一個計算(字符串)來評估字符串類型的操作數,例如「2 + 3」。 我已經嘗試了很多操作數和方法工作正常,除了這個: 計算(「2.002 * 1000)//返回2001.9999999999 我很好奇這個錯誤怎麼發生的我經歷了很多次代碼,我想不通問題出在哪裏Java方法計算(「2.002 * 1000」)//返回2001.999999999999

下面的代碼:。

private String calculate(String str) 
    { 
     String num = ""; 
     List<String> list = new ArrayList<String>(); 
     for(int i = 0; i < str.length(); i++) //Arrange str into list, elements are seperated by "+" or "-" 
     { 
      if(! checkPM(str.substring(i, i + 1))) 
      { 
       num = num + str.substring(i, i + 1); 
      } else 
      { 
       list.add(num); 
       list.add(str.substring(i, i + 1)); 
       num = ""; 
      } 
     } 
     list.add(num);//add the last num into list 
     if(checkSign(list.get(list.size() - 1)))//remove last element if it is an operator 
     { 
     list.remove(list.get(list.size() - 1)); 
     } 
     String numlistele = ""; //Elements of numlist 
     List<String> numlist = new ArrayList<String>(); //List of numbers to be TD 
     List<String> TDlist = new ArrayList<String>(); //List of times or divide 
     for(int j = 0; j < list.size(); j++) //Check which of the elements of list contains "*" or "/" 
     { 
      String tdAns = ""; //Answer of numlistele timed or divided 
      if(checkTD(list.get(j))) // When the elements of list contains "*" or "/" 
      { 
       for(int k = 0; k < list.get(j).length(); k++) // 
       { 
        if(! checkSign(list.get(j).substring(k, k + 1))) 
        { 
         numlistele = numlistele + list.get(j).substring(k, k+1); 
        } else 
        { 
         numlist.add(numlistele); 
         TDlist.add(list.get(j).substring(k, k+1)); 
         numlistele = ""; 
        } 
       } 
       numlist.add(numlistele); //Adds the last number into numlist 
       numlistele = ""; //Restore numlistele to "", to be used in next loop 
       tdAns = numlist.get(0); //Answer of numlistele timed or divided, firstly it is equals to the first elements of numlist 
       for(int l = 0; l < TDlist.size(); l++) 
       { 
        if(TDlist.get(l).equals("×")) 
        { 
         double tempdou = Double.parseDouble(tdAns) * //temporary double used to save to tdANS 
           Double.parseDouble(numlist.get(l+1)); 
         tdAns = String.valueOf(tempdou); 
        } else //when TDlist.get(l).equals("/") is true 
        { 
         double tempdou = Double.parseDouble(tdAns)/
           Double.parseDouble(numlist.get(l+1)); 
         tdAns = String.valueOf(tempdou); 
        } 
       } 
      list.set(j, tdAns); 
      }    
      numlist.clear(); //Clear numlist for next loop 
      TDlist.clear(); //Clear TDlist for next loop 
     } 
     String ans = list.get(0); //Will become final answer later, first it is assign to first element of list 
     for(int m = 0; m < list.size(); m++) 
     { 
      if(list.get(m).equals("+")) 
      { 
       double tempdou = Double.parseDouble(ans) + //Temporary double used to save to ans 
         Double.parseDouble(list.get(m + 1)); 
       ans = String.valueOf(tempdou); 
      } else if(list.get(m).equals("-")) 
      { 
       double tempdou = Double.parseDouble(ans) - 
         Double.parseDouble(list.get(m + 1)); 
       ans = String.valueOf(tempdou); 
      } 
     } 
     if(ans.length() > 2) 
     { 
      if(ans.substring(ans.length() - 2).equals(".0")) //To remove .0 of the answer 
      { 
       ans = ans.substring(0, ans.length() - 2); 
      } 

     } 
     return ans; 
    } 

在此先感謝

+6

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

+0

@Nambari我正要張貼自己 – Will

回答

2

這是浮點數學教材的情況下,你所mul​​tipled本來就不是2.002 * 1000.相反,這是一個接近2.002倍的數字由一個數字接近1000.

如果你需要絕對精度,你應該使用一些java的BigDecimal類型。在C#中,您可以使用decimal類型。

http://en.wikipedia.org/wiki/Round-off_error

http://en.wikipedia.org/wiki/Floating_point

+0

謝謝你,有沒有什麼辦法來解決這個問題? – user2236096

+0

我懂了!謝謝! – user2236096

6

浮點表示並不總是準確的。當您分析字符串「2.002」時,Double.parseDouble返回了最接近的double表示形式。

當乘以1000時,浮點表示中的錯誤變得足夠大以至於通知(2001.999999999999)。

這是good online article about floating point representation和可能發生的事故。

爲了確保浮點數的準確表示,您可以使用Java的內置BigDecimal類。它可能不那麼快,但它會保留你需要的所有精度。

+0

我明白了。謝謝! – user2236096