2013-07-12 27 views
1

我試圖讓Android的一個基本的計算器程序,但我是新到Android以及Java
但我相信這可能是更多的是java的問題
的的界面的按鈕爲0到9,小數點,等於符號,+, - ,*,/和取消(重置所有變量)
尾數存儲在一個雙變量中,我用String.valueOf(mantissa_value)將其轉換爲要在TextView控件上顯示的字符串
當我鍵入2.331時,尾數顯示爲2.33099999(10個字符是存儲尾數文本的字符串變量的限制),但是我f我再次按1,它顯示2.3311。爲什麼會發生這種情況,我該如何解決?不穩定的雙可變行爲

相關代碼(大概):

public void onClkBn1(View view){ 
    if(decimalClicked == false) 
     mantissa_value = mantissa_value*10+1; 
    else{ 
     mantissa_value = mantissa_value + pow(10, -numOfClicksAfterDecimal)*1; 
     numOfClicksAfterDecimal++; 
    } 
    updateMantissa(); 
} 

public void updateMantissa(){ 
    if(mantissa_value == 0){ 
     mantissa_str = "0"; 
    } 

    else if(ceil(mantissa_value) == mantissa_value){ 
     mantissa_str = String.valueOf(mantissa_value); 
     mantissa_str = mantissa_str.substring(0, mantissa_str.length() - 2); 
    } 

    else{ 
     mantissa_str = String.valueOf(mantissa_value); 
     mantissa_str = mantissa_str.substring(0, Math.min(mantissa_str.length(), 10)); 
    } 
    TextView thisText = (TextView) findViewById(R.id.mantissa); 
    thisText.setText(mantissa_str); 
} 

全碼:

package com.example.calculator; 

import android.os.Bundle; 
import android.app.Activity; 
import android.view.Menu; 
import android.view.View; 
import android.widget.TextView; 
import static java.lang.Math.pow; 
import static java.lang.Math.ceil; 

public class MainActivity extends Activity { 
private double mantissa_value = 0; 
private double opr1 = 0; 
private double opr2 = 0; 
private double res = 0; 
private enum OprTypes {NONE, PLUS, MINUS, MULT, DIV} 
OprTypes oprLatest = OprTypes.NONE; 
private boolean oprPlusClicked = false; 
private boolean oprMinusClicked = false; 
private boolean oprMultClicked = false; 
private boolean oprDivClicked = false; 
private boolean decimalClicked = false; 
private double numOfClicksAfterDecimal = 1; 
private String mantissa_str; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    updateMantissa(); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
} 

public void updateMantissa(){ 
    if(mantissa_value == 0){ 
     mantissa_str = "0"; 
    } 

    else if(ceil(mantissa_value) == mantissa_value){ 
     mantissa_str = String.valueOf(mantissa_value); 
     mantissa_str = mantissa_str.substring(0, mantissa_str.length() - 2); 
    } 

    else{ 
     mantissa_str = String.valueOf(mantissa_value); 
     mantissa_str = mantissa_str.substring(0, Math.min(mantissa_str.length(), 10)); 
    } 
    TextView thisText = (TextView) findViewById(R.id.mantissa); 
    thisText.setText(mantissa_str); 
} 

public void onClkBn0(View view){ 
    TextView thisText = (TextView) findViewById(R.id.mantissa); 
    if(decimalClicked == false){ 
     mantissa_value = mantissa_value*10+0; 
     updateMantissa(); 
    } 
    else{ 
     if(mantissa_value == 0){ 
      if(numOfClicksAfterDecimal == 1){ 
       mantissa_str = mantissa_str + ".0"; 
      } 
      else{ 
       mantissa_str = mantissa_str + "0"; 
      } 
     } 

     else if(ceil(mantissa_value) == mantissa_value){ 
      if(numOfClicksAfterDecimal == 1){ 
       mantissa_str = mantissa_str + ".0"; 
      } 
      else{ 
       mantissa_str = mantissa_str + "0"; 
      } 
     } 

     mantissa_value = mantissa_value + pow(10, -numOfClicksAfterDecimal)*0; 
     numOfClicksAfterDecimal++; 
     thisText.setText(mantissa_str); 
    } 
} 

public void onClkBn1(View view){ 
    if(decimalClicked == false) 
     mantissa_value = mantissa_value*10+1; 
    else{ 
     mantissa_value = mantissa_value + pow(10, -numOfClicksAfterDecimal)*1; 
     numOfClicksAfterDecimal++; 
    } 
    updateMantissa(); 
} 

public void onClkBn2(View view){ 
    if(decimalClicked == false) 
     mantissa_value = mantissa_value*10+2; 
    else{ 
     mantissa_value = mantissa_value + pow(10, -numOfClicksAfterDecimal)*2; 
     numOfClicksAfterDecimal++; 
    } 
    updateMantissa(); 
} 

public void onClkBn3(View view){ 
    if(decimalClicked == false) 
     mantissa_value = mantissa_value*10+3; 
    else{ 
     mantissa_value = mantissa_value + pow(10, -numOfClicksAfterDecimal)*3; 
     numOfClicksAfterDecimal++; 
    } 
    updateMantissa(); 
} 

public void onClkBn4(View view){ 
    if(decimalClicked == false) 
     mantissa_value = mantissa_value*10+4; 
    else{ 
     mantissa_value = mantissa_value + pow(10, -numOfClicksAfterDecimal)*4; 
     numOfClicksAfterDecimal++; 
    } 
    updateMantissa(); 
} 

public void onClkBn5(View view){ 
    if(decimalClicked == false) 
     mantissa_value = mantissa_value*10+5; 
    else{ 
     mantissa_value = mantissa_value + pow(10, -numOfClicksAfterDecimal)*5; 
     numOfClicksAfterDecimal++; 
    } 
    updateMantissa(); 
} 

public void onClkBn6(View view){ 
    if(decimalClicked == false) 
     mantissa_value = mantissa_value*10+6; 
    else{ 
     mantissa_value = mantissa_value + pow(10, -numOfClicksAfterDecimal)*6; 
     numOfClicksAfterDecimal++; 
    } 
    updateMantissa(); 
} 

public void onClkBn7(View view){ 
    if(decimalClicked == false) 
     mantissa_value = mantissa_value*10+7; 
    else{ 
     mantissa_value = mantissa_value + pow(10, -numOfClicksAfterDecimal)*7; 
     numOfClicksAfterDecimal++; 
    } 
    updateMantissa(); 
} 

public void onClkBn8(View view){ 
    if(decimalClicked == false) 
     mantissa_value = mantissa_value*10+8; 
    else{ 
     mantissa_value = mantissa_value + pow(10, -numOfClicksAfterDecimal)*8; 
     numOfClicksAfterDecimal++; 
    } 
    updateMantissa(); 
} 

public void onClkBn9(View view){ 
    if(decimalClicked == false) 
     mantissa_value = mantissa_value*10+9; 
    else{ 
     mantissa_value = mantissa_value + pow(10, -numOfClicksAfterDecimal)*9; 
     numOfClicksAfterDecimal++; 
    } 
    updateMantissa(); 
} 

public void onClkBnDot(View view){ 
    decimalClicked = true; 
} 

public void onClkBnCan(View view){ 
    mantissa_value = 0; 
    opr1 = 0; 
    opr2 = 0; 
    res = 0; 
    oprLatest = OprTypes.NONE; 
    oprPlusClicked = false; 
    oprMinusClicked = false; 
    oprMultClicked = false; 
    oprDivClicked = false; 
    decimalClicked = false; 
    numOfClicksAfterDecimal = 1; 
} 


public void onClkBnPlus(View view){ 
    if(oprPlusClicked == false){ 
     oprPlusClicked = true; 
     opr1 = mantissa_value; 
     mantissa_value = 0; 
    } 
    else{ 
     // this should mean opr1 already has some value in it 
     // so add the current mantissa value to opr1 
     opr1 = opr1 + mantissa_value; 
     mantissa_value = 0; 
    } 
    oprLatest = OprTypes.PLUS; 
} 


public void onClkBnMinus(View view){ 
    if(oprMinusClicked == false){ 
     oprMinusClicked = true; 
     opr1 = mantissa_value; 
     mantissa_value = 0; 
    } 
    else{ 
     // this should mean opr1 already has some value in it 
     // so add the current mantissa value to opr1 
     opr1 = opr1 - mantissa_value; 
     mantissa_value = 0; 
    } 
    oprLatest = OprTypes.MINUS; 
} 

public void onClkBnMult(View view){ 
    if(oprMultClicked == false){ 
     oprMultClicked = true; 
     opr1 = mantissa_value; 
     mantissa_value = 0; 
    } 
    else{ 
     // this should mean opr1 already has some value in it 
     // so add the current mantissa value to opr1 
     opr1 = opr1 * mantissa_value; 
     mantissa_value = 0; 
    } 
    oprLatest = OprTypes.MULT; 
} 

public void onClkBnDiv(View view){ 
    if(oprDivClicked == false){ 
     oprDivClicked = true; 
     opr1 = mantissa_value; 
     mantissa_value = 0; 
    } 
    else{ 
     // this should mean opr1 already has some value in it 
     // so add the current mantissa value to opr1 
     opr1 = opr1/mantissa_value; 
     mantissa_value = 0; 
    } 
    oprLatest = OprTypes.DIV; 
} 


public void onClkBnRes(View view){ 
    if(oprPlusClicked == true || oprMinusClicked == true || oprMultClicked == true || oprDivClicked == true){ 
     switch(oprLatest){ 
     case PLUS: 
      mantissa_value = opr1 + mantissa_value; 
      break; 
     case MINUS: 
      mantissa_value = opr1 - mantissa_value; 
      break; 
     case MULT: 
      mantissa_value = opr1 * mantissa_value; 
      break; 
     case DIV: 
      mantissa_value = opr1/mantissa_value; 
      break; 
     case NONE: 
      break; 
     } 
    } 
    oprLatest = OprTypes.NONE; 
    oprPlusClicked = false; 
    oprMinusClicked = false; 
    oprMultClicked = false; 
    oprDivClicked = false; 
    updateMantissa(); 
} 
} 
+0

@JBNizet:所以這不是一個java的問題呢?如果我只是在我的程序中使用雙變量而不是試圖將它們顯示爲文本呢?這在這種情況下應該沒有什麼重要的影響? – user13267

+0

不,這不是Java問題。這是一個有限與無限的問題。您無法使用64位表示無窮大或實際值。如果你想要確切的值,不要使用double。如果近似值很好,那麼double就是OK。 –

+0

所以2.331沒有確切的表示,但是2.3311呢?爲了解決這個問題,我將如何檢查哪個特定的浮點數沒有確切的表示形式,或者是否可以獲取String.valueOf()以獲取近似值的字符串等效值(僅使用基本數據類型而不使用答案中建議BigDecimal)? – user13267

回答

1

一個雙Java中的說法並不確切。它可以通過使用BigDecimal的

固定

How to resolve a Java Rounding Double issue

+0

爲什麼它在Java中是這樣的?如果我只是在一系列長計算中使用雙變量,而不是試圖將其顯示爲文本?這會導致最終結果發生顯着變化,還是大多數計算可以忽略不計? – user13267

+0

IMO錯誤是錯誤的。我看到有這麼多人被抓到,特別是在使用Double進行金錢交易時。你可以成爲你自己的裁判,你是否可以用雙打「生活」,但也許幾年後你會後悔。 –