我正在为android编写一个基本的单位转换器。这是我的计划:
package com.airavataunitconverter;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import com.airavataunitconverter.R.id;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Typeface;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
public class LengthConverter extends Activity {
Spinner spr_unit_l;
EditText et_input_l;
TextView tv_result_nm;
TextView tv_result_mm;
TextView tv_result_cm;
TextView tv_result_dm;
TextView tv_result_m;
TextView tv_result_km;
TextView tv_result_in;
TextView tv_result_ft;
TextView tv_result_yd;
TextView tv_result_mi;
TextView tv_result_nmi;
TextView tv_nm;
TextView tv_mm;
TextView tv_cm;
TextView tv_dm;
TextView tv_m;
TextView tv_km;
TextView tv_in;
TextView tv_ft;
TextView tv_yd;
TextView tv_mi;
TextView tv_nmi;
BigDecimal nm;
BigDecimal mm;
BigDecimal cm;
BigDecimal dm;
BigDecimal m;
BigDecimal km;
BigDecimal in ;
BigDecimal ft;
BigDecimal yd;
BigDecimal mi;
BigDecimal nmi;
BigDecimal zero;
BigDecimal bd_input_number_length;
String str_nm = "nanometer";
String str_mm = "millimeter";
String str_cm = "centimeter";
String str_dm = "decimeter";
String str_m = "meter";
String str_km = "kilometer";
String str_in = "inch";
String str_ft = "feet";
String str_yd = "yard";
String str_mi = "mile";
String str_nmi = "nautical mile";
String STR_INPUT_UNIT_LENGTH;
int input_unit_length;
int int_input_unit_length;
String STR_INPUT_NUMBER_LENGTH;
String str_unit_length;
ArrayAdapter < String > myAdap;
int unit_selected_nm;
int unit_selected_mm;
int unit_selected_cm;
int unit_selected_dm;
int unit_selected_m;
int unit_selected_km;
int unit_selected_in;
int unit_selected_ft;
int unit_selected_yd;
int unit_selected_mi;
int unit_selected_nmi;
String input_number_length;
BigDecimal bd_referance;
BigDecimal bd_nm;
BigDecimal bd_mm;
BigDecimal bd_cm;
BigDecimal bd_dm;
BigDecimal bd_m;
BigDecimal bd_km;
BigDecimal bd_in;
BigDecimal bd_ft;
BigDecimal bd_yd;
BigDecimal bd_mi;
BigDecimal bd_nmi;
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_length_converter);
spr_unit_l = (Spinner) findViewById(R.id.spinner_length_unit);
nm = new BigDecimal(0.000000001);
mm = new BigDecimal(.001);
cm = new BigDecimal(0.01);
dm = new BigDecimal(0.1);
m = new BigDecimal(1);
km = new BigDecimal(1000); in = new BigDecimal(0.0254);
ft = new BigDecimal(0.3048);
yd = new BigDecimal(0.9144);
mi = new BigDecimal(1609.344);
nmi = new BigDecimal(1852);
zero = BigDecimal.ZERO;
String str_unit_length[] = {
str_nm, str_mm, str_cm, str_dm, str_m,
str_km, str_in, str_ft, str_yd, str_mi, str_nmi
};
myAdap = new ArrayAdapter < String > (this,
android.R.layout.simple_spinner_item, str_unit_length);
myAdap.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spr_unit_l.setAdapter(myAdap);
sharedpref = getSharedPreferences(MyPreferences, Context.MODE_PRIVATE);
et_input_l = (EditText) findViewById(R.id.edittext_length_input);
tv_nm = (TextView) findViewById(R.id.textview_nm);
tv_mm = (TextView) findViewById(R.id.textview_mm);
tv_cm = (TextView) findViewById(R.id.textview_cm);
tv_dm = (TextView) findViewById(R.id.textview_dm);
tv_m = (TextView) findViewById(R.id.textview_m);
tv_km = (TextView) findViewById(R.id.textview_km);
tv_in = (TextView) findViewById(R.id.textview_in);
tv_ft = (TextView) findViewById(R.id.textview_ft);
tv_yd = (TextView) findViewById(R.id.textview_yd);
tv_mi = (TextView) findViewById(R.id.textview_mi);
tv_nmi = (TextView) findViewById(R.id.textview_nmi);
tv_result_nm = (TextView) findViewById(R.id.textview_result_nm);
tv_result_mm = (TextView) findViewById(R.id.textview_result_mm);
tv_result_cm = (TextView) findViewById(R.id.textview_result_cm);
tv_result_dm = (TextView) findViewById(R.id.textview_result_dm);
tv_result_m = (TextView) findViewById(R.id.textview_result_m);
tv_result_km = (TextView) findViewById(R.id.textview_result_km);
tv_result_in = (TextView) findViewById(R.id.textview_result_in);
tv_result_ft = (TextView) findViewById(R.id.textview_result_ft);
tv_result_yd = (TextView) findViewById(R.id.textview_result_yd);
tv_result_mi = (TextView) findViewById(R.id.textview_result_mi);
tv_result_nmi = (TextView) findViewById(R.id.textview_result_nmi);
spr_unit_l.setOnItemSelectedListener(new OnItemSelectedListener() {
@
Override
public void onItemSelected(AdapterView <? > arg0, View arg1,
int arg2, long arg3) {
// TODO Auto-generated method stub
final_length_convert();
}
@
Override
public void onNothingSelected(AdapterView <? > arg0) {
// TODO Auto-generated method stub
}
});
et_input_l.addTextChangedListener(new TextWatcher() {
@
Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
final_length_convert();
}
@
Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
// TODO Auto-generated method stub
}
@
Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.length_converter, menu);
return true;
}
private int getIndex(Spinner spinner, String myString) {
int index = 0;
for (int i = 0; i < spinner.getCount(); i++) {
if (spinner.getItemAtPosition(i).equals(myString)) {
index = i;
i = spr_unit_l.getCount();
}
}
return index;
}
private void final_length_convert() {
if (et_input_l.getText().toString().equals("") || et_input_l.getText().toString().equals(".") || et_input_l.getText().toString().equals("-")) {
tv_result_nm.setText(zero.toPlainString());
tv_result_mm.setText(zero.toPlainString());
tv_result_cm.setText(zero.toPlainString());
tv_result_dm.setText(zero.toPlainString());
tv_result_m.setText(zero.toPlainString());
tv_result_km.setText(zero.toPlainString());
tv_result_in.setText(zero.toPlainString());
tv_result_ft.setText(zero.toPlainString());
tv_result_yd.setText(zero.toPlainString());
tv_result_mi.setText(zero.toPlainString());
tv_result_nmi.setText(zero.toPlainString());
} else if (spr_unit_l.getSelectedItem().equals(str_nm)) {
bd_referance = nm;
length_convert();
} else if (spr_unit_l.getSelectedItem().equals(str_mm)) {
bd_referance = mm;
length_convert();
} else if (spr_unit_l.getSelectedItem().equals(str_cm)) {
bd_referance = cm;
length_convert();
} else if (spr_unit_l.getSelectedItem().equals(str_dm)) {
bd_referance = dm;
length_convert();
} else if (spr_unit_l.getSelectedItem().equals(str_m)) {
bd_referance = m;
length_convert();
} else if (spr_unit_l.getSelectedItem().equals(str_km)) {
bd_referance = km;
length_convert();
} else if (spr_unit_l.getSelectedItem().equals(str_in)) {
bd_referance = in ;
length_convert();
} else if (spr_unit_l.getSelectedItem().equals(str_ft)) {
bd_referance = ft;
length_convert();
} else if (spr_unit_l.getSelectedItem().equals(str_yd)) {
bd_referance = yd;
length_convert();
} else if (spr_unit_l.getSelectedItem().equals(str_mi)) {
bd_referance = mi;
length_convert();
} else if (spr_unit_l.getSelectedItem().equals(str_nmi)) {
bd_referance = nmi;
length_convert();
}
}
private void length_convert() {
bd_input_number_length = new BigDecimal(et_input_l.getText().toString());
bd_nm = bd_input_number_length.multiply(
(bd_referance).divide(nm, 4, RoundingMode.HALF_EVEN))
.stripTrailingZeros();
bd_mm = bd_input_number_length.multiply(
(bd_referance).divide(mm, 4, RoundingMode.HALF_EVEN))
.stripTrailingZeros();
bd_cm = bd_input_number_length.multiply(
(bd_referance).divide(cm, 4, RoundingMode.HALF_EVEN))
.stripTrailingZeros();
bd_dm = bd_input_number_length.multiply(
(bd_referance).divide(dm, 4, RoundingMode.HALF_EVEN))
.stripTrailingZeros();
bd_m = bd_input_number_length.multiply(
(bd_referance).divide(m, 4, RoundingMode.HALF_EVEN))
.stripTrailingZeros();
bd_km = bd_input_number_length.multiply(
(bd_referance).divide(km, 4, RoundingMode.HALF_EVEN))
.stripTrailingZeros();
bd_in = bd_input_number_length.multiply(
(bd_referance).divide( in , 4, RoundingMode.HALF_EVEN))
.stripTrailingZeros();
bd_ft = bd_input_number_length.multiply(
(bd_referance).divide(ft, 4, RoundingMode.HALF_EVEN))
.stripTrailingZeros();
bd_yd = bd_input_number_length.multiply(
(bd_referance).divide(yd, 4, RoundingMode.HALF_EVEN))
.stripTrailingZeros();
bd_mi = bd_input_number_length.multiply(
(bd_referance).divide(mi, 4, RoundingMode.HALF_EVEN))
.stripTrailingZeros();
bd_nmi = bd_input_number_length.multiply(
(bd_referance).divide(nmi, 4, RoundingMode.HALF_EVEN))
.stripTrailingZeros();
tv_result_nm.setText(bd_nm.toPlainString());
tv_result_mm.setText(bd_mm.toPlainString());
tv_result_cm.setText(bd_cm.toPlainString());
tv_result_dm.setText(bd_dm.toPlainString());
tv_result_m.setText(bd_m.toPlainString());
tv_result_km.setText(bd_km.toPlainString());
tv_result_in.setText(bd_in.toPlainString());
tv_result_ft.setText(bd_ft.toPlainString());
tv_result_yd.setText(bd_yd.toPlainString());
tv_result_mi.setText(bd_mi.toPlainString());
tv_result_nmi.setText(bd_nmi.toPlainString());
}
public void save(View view) {
sharedpref_editor = sharedpref.edit();
sharedpref_editor.putInt(STR_INPUT_UNIT_LENGTH,
spr_unit_l.getSelectedItemPosition());
sharedpref_editor.commit();
}
}
我已经写过它,因此当用户键入或更改微调器中的项目时,不会自动为用户进行转换,即不需要转换&#34;按钮。我最初使用double计算数字,但有时会导致错误,如0.9999999999997,当它应该显示1.在搜索解决方案后,我认为最好使用BigDecimal,因为他们没有这些类型的错误。不幸的是,这些类型的错误仍然存在(例如,输入km = 1显示nm = 999999999999.9999而不是1000000000000,但其他转换仍然正确)。谁能指出我做错了什么?
答案 0 :(得分:1)
正如我在评论中提到的,您的问题是在BigDecimal构造函数中输入双精度,这是您在键入new BigDecimal(0.000000001);
时所执行的操作。从概念上讲,您正在执行以下操作
double
表示(引入非常小的错误)BigDecimal
表示。正如您所看到的,您无法避免Base 10和Base 2之间转换的初始错误。
您需要做的是使用String
BigDecimal
输入来避免中间Base 2表示:
new BigDecimal("0.000000001");