Plus or minus minor glitch in my android calculator - java

I have made an android calculator, and I have added the +/- button to it recently. The problems I am facing is, firstly when I use it, and press the equal button, the app crashes. Moreover as soon as I click +/- button, the digits turn into a float value, and when I type any number the number value continues after the decimal. Example: I have 200 and I press +/- the number becomes 200.0 and when I type any number it becomes 200.01. How do I overcome this problem? Can someone please let me know what are the changes required in my code? Here it is.
Thank you. :)
public class MainActivity extends Activity {
Typeface font1, font2;
TextView tv1;
private EditText Scr; //textbox screen
private float NumberBf; //Save screen before pressing button operation;
private String Operation;
private ButtonClickListener btnClick;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
font1=Typeface.createFromAsset(getAssets(), "digits.ttf");
Scr=(EditText)findViewById(R.id.editText);
Scr.setTypeface(font1);
font2=Typeface.createFromAsset(getAssets(), "alexbrush.TTF");
tv1=(TextView)findViewById(R.id.textView1);
tv1.setTypeface(font2);
Scr = (EditText) findViewById(R.id.editText);
Scr.setEnabled(false);
btnClick = new ButtonClickListener();
int idList[] = {R.id.button0,R.id.button7, R.id.button1, R.id.button8,R.id.button9,R.id.button4,
R.id.button5,R.id.button6,R.id.button,R.id.button2,R.id.button3,R.id.buttonDot,
R.id.buttonMul,R.id.buttonDiv,R.id.buttonAdd,R.id.buttonSub,R.id.buttonC,
R.id.buttonEq, R.id.buttonSqrt, R.id.buttonsquare, R.id.buttonNp
};
for(int id:idList){
View v = (View) findViewById(id);
v.setOnClickListener(btnClick);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void mMath(String str){
NumberBf = Float.parseFloat(Scr.getText().toString()); //save the screen
Operation = str; //save operation
Scr.setText("0"); //Clear screen
}
public void getKeyboard(String str){
String ScrCurrent = Scr.getText().toString();
if(ScrCurrent.equals("0"))
ScrCurrent = "";
ScrCurrent += str;
Scr.setText(ScrCurrent);
}
public void mResult(){
float NumAf = Float.parseFloat(Scr.getText().toString());
float result = 0;
if(Operation.equals("+")){
result = NumAf + NumberBf;
}
if(Operation.equals("-")){
result = NumberBf - NumAf;
}
if(Operation.equals("*")){
result = NumAf * NumberBf;
}
if(Operation.equals("/")){
result = NumberBf / NumAf;
}
Scr.setText(String.format("%10d", result));
}
public void fnSqrt(){
double Number = Double.parseDouble(Scr.getText().toString());
Number = Math.sqrt(Number);
Scr.setText(String.valueOf(Number));
}
public void fnSquare(){
float Number1 = Float.parseFloat(Scr.getText().toString());
Number1 = pow(Number1, 2);
Scr.setText(String.valueOf(Number1));
}
public void fnNp(){
float Number = Float.parseFloat(Scr.getText().toString());
Number = Number*(-1);
Scr.setText(String.valueOf(Number));
}
private float pow(float number1, int i) {
return number1*number1;
}
private class ButtonClickListener implements OnClickListener{
public void onClick(View v){
switch (v.getId()){
case R.id.buttonC: //Clear screen
Scr.setText("0");
NumberBf = 0;
Operation = "";
break;
case R.id.buttonAdd: //function Add
mMath("+");
break;
case R.id.buttonSub:
mMath("-");
break;
case R.id.buttonMul:
mMath("*");
break;
case R.id.buttonDiv:
mMath("/");
break;
case R.id.buttonEq:
mResult();
break;
case R.id.buttonSqrt:
fnSqrt();
break;
case R.id.buttonNp:
fnNp();
break;
case R.id.buttonsquare:
fnSquare();
break;
default:
String numb = ((Button) v).getText().toString();
getKeyboard(numb);
break;
}
}
}
}

Concerning your first problem: Do you get a nullpointer exception?
public void mResult(){
float NumAf = Float.parseFloat(Scr.getText().toString());
does not prevents your statement to try to turn a null String into a float which obviously will let your app crash. So include a mechanism to catch the null value before.
case R.id.buttonEq:
if (Scr.getText() != null)
mResult();
break;
I think this is the easiest way to prevent your mResult() from getting a null value.
For your second problem: It becomes a float because you do
float Number = Float.parseFloat(Scr.getText().toString());`
When you cast your 200 into a float it becomes 200.00 which will be returned as a string.
EDIT: I realized that you also have a dotButton (your code is really messy). The suggested alternative of course does not work with decimal numbers because it always casts your numbervalue. To prevent this behaviour maybe you can implement a simple if/else statement.
public void fnNp() {
if (Scr.getText().toString().contains(".")) {
float Number = Float.parseFloat(Scr.getText().toString());
Number = Number*(-1);
Scr.setText(String.valueOf(Number));
} else {
int number = Integer.parseInt(Scr.getText().toString());
Number = Number*(-1);
Scr.setText(String.valueOf(Number));
}
}

You need to do a if statement in mResult that checks whether the float has a absolute difference to a float of the int of the float , less than , say Float.MIN_VALUE , and then get the toString of the int of the float instead if it is.
Wrap the call Scr.setText( Float f) , in a function setScreenTextWithNumber(Number n)
and do the checking there.
If you just check for the decimal point, then 2.0000 / 2 = 1.000 if that is what you want.
Otherwise checking for significant differences makes a call that a number that is not significantly different from the nearest integer is an integer.

Related

How to display the float value of a calculation in a text box?

I'm trying to display the 'Day time left' and 'Night time left'
after doing a small calculation
I want to be able to select any of the 3 packages from the combo box
then when I click calculate it should do the calculation and display the result in the text boxes.
I tried converting a float value to string and then display in the text box, It worked !!
so that means this calculation doesen't work.
Somehow the calculation doesn't work so it always displays the value as 0.0
private void jButton1MouseClicked(java.awt.event.MouseEvent evt) {
day_left = tot_day_time - day_used;
night_data = tot_all_time - tot_day_time;
night_left = night_data - night_used;
jTextPane3.setText(Float.toString(day_left));jTextPane2.setText(Float.toString(night_left));
}
I always get 0.0
package slt_package;
public class slt_jframe extends javax.swing.JFrame {
float tot_day_time;
float tot_all_time;
float night_used;
float day_used;
float day_left;
float night_left;
float night_data;
private void package_comboboxActionPerformed(java.awt.event.ActionEvent evt) {
int selectedPackage = package_combobox.getSelectedIndex();
switch (selectedPackage) {
case 0:
tot_day_time = 85;tot_all_time = 205;
break;
case 1:
tot_day_time = 105;tot_all_time = 260;
break;
case 2:
tot_day_time = 190;tot_all_time = 280;
break;
default:
break;
}
}
private void textField1ActionPerformed(java.awt.event.ActionEvent evt) {
day_used=Float.parseFloat(textField1.getSelectedText()); // TODO add your handling code here:
}
private void textField2ActionPerformed(java.awt.event.ActionEvent evt) {
night_used=Float.parseFloat(textField2.getSelectedText());
// TODO add your handling code here:
}
private void jButton1MouseClicked(java.awt.event.MouseEvent evt) {
day_left = tot_day_time - day_used;
night_data = tot_all_time - tot_day_time;
night_left = night_data - night_used;
jTextPane3.setText(Float.toString(day_left));
jTextPane2.setText(Float.toString(night_left));
}
}
As Andrew wrote, it's difficult to find the bug without a working program. I would double-check the Float.toString method as seen in Float to String format specifier.

Using a running total for calculator

I made a calculator on android. I get results for only two numbers (1+1), but I would like to be able to do more then one calculation at a time instead of hitting enter every time I need a new answer (1+1-2).
Something like this: 2 + 2 (new operator pressed) 4 + 3 (equals is pressed) 7
But I'm not sure how to implement this on my code.
This is the button code for every operator:
btnPlus.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
perform();
operation = "+";
}
}); // end btnPlus
This is my calculation method:
private void calculate() {
if (operation == null) {
numberInput.setText(null);
} else if (operation.equals("+")){
numResult = (secondNum + firstNum);
numberInput.setText(String.valueOf(numResult));
} else if (operation.equals("-")) {
numResult = (secondNum - firstNum);
numberInput.setText(String.valueOf(numResult));
} else if (operation.equals("/")) {
numResult = (secondNum / firstNum);
numberInput.setText(String.valueOf(numResult));
} else if (operation.equals("*")) {
numResult = (secondNum * firstNum);
numberInput.setText(String.valueOf(numResult));
} // end if statement
}
Also, perform if needed:
private void perform() {
str = "";
secondNum = firstNum;
}
A quick way to solve your problem given your current code is to use textChangeListener/TextWatcher(assuming you have an EditText or TextView) to detect every time an operator is entered then call the operate function. It would look something like this.
myEditText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
public void onTextChanged(CharSequence s, int start,
int before, int count) {
// if 2nd operator is detected
// call calculate
// append 2nd operator
}
});
You could do as i suggested in the comment, and just make a list for every operation, and then calculate it every time the current data changes (there may be difffrent ways to "know" if some of the result is final depending on how you can delete from the app.
SOmething like this is what i would do, and then just everytime a button is pressed call the logic for adding the input, and then calculate it and write it out
public class Calc {
private List<String> inputs = new ArrayList<>();
public String calculate(List<String> input){
String result = "";
for(String current : input){
switch (current) {
case "(":
// do stuff
case "+":
//do stuff
default:
// do stuff
}
}
return result;
}
btnPlus.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// add to list, and call calculate
}
}); // end btnPlus
}

How to set textview as method output in andrioid?

I have just started to use android studio recently and currently I am working on a Roman Numeral Translator app. The app's interface looks like this: Application interface
The user will use the keypad to input a integer which will show up on the TextView shown above. When they hit the convert button it will take the integer they have entered and convert it (the program will be able to catch the input if contains a string or character). Then the app will reset the TextView to the result after the user hits the "convert" button.
Currently, my main activity contains the onClickListeners for the buttons and a separate translator method for the translations. My problem is with the "convert" button I'm not sure how to get the input from the translator method and set it as TextView when it finishes converting. Here is the sample of my code:
"Convert" button listener- `
convert.setOnClickListener(
new View.OnClickListener() {
public void onClick(View v) {
TextView numeralInput = (TextView) findViewById(R.id.textView);
String intValue = numeralInput.getText().toString();
try{
int integer = Integer.parseInt(intValue);
if (integer > 0 && integer <= 4999){
translator(integer);
}else{
numeralInput.setText("Please enter an integer between 0 and 4,999.");
}
}catch(NumberFormatException e){
numeralInput.setText("Invalid input try again.");
}
}
}
);
`
Translator Method- `
public static void translator(int integer) {
LinkedList<String> stack = new LinkedList<String>();
// if (integer > 0 && integer <= 4999) {
//ArrayList<Integer> placement = new ArrayList<Integer>();
int place = (int) Math.log10(integer);
for (int i = 0; i <= place; i++) {
//while(integer > 0){
//System.out.println(integer);
int placeOfValue = integer % 10;
//stack.push(placeOfValue);
//System.out.print(stack);
//System.out.print(placeOfValue +":" + i);
String placement = "";
switch (i) {
case 0:
placement = ones(placeOfValue);
break;
case 1:
placement = tens(placeOfValue);
break;
case 2:
placement = hundreds(placeOfValue);
break;
case 3:
placement = thousands(placeOfValue);
break;
default:
break;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
stack.push(placement);
}
integer = integer / 10;
//System.out.print(placement);
// System.out.println(placement.size());
//}
// for(int j = 0; j < placement.size(); j++){
// double tenthPower = Math.floor(Math.log10(placement.get(j)));
// double place = Math.pow(10, tenthPower);
// System.out.println(place);
//
// }
// }
while (!stack.isEmpty()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
System.out.print(stack.pop());
}
}
// } else {
// System.out.println("Please enter an integer between 0 and 4,999.");
// }
}
}
`
The other methods inside translator is like a library for the roman numerals each containing a numeral for each of the place values as shown below.
Thousands method- `
public static String thousands(int integer) {
String thouValue = "";
switch (integer) {
case 1:
thouValue = "M";
//System.out.print("M");
break;
case 2:
thouValue = "MM";
//System.out.print("MM");
break;
case 3:
thouValue = "MMM";
//System.out.print("MMM");
break;
case 4:
thouValue = "MMMM";
//System.out.print("MMMM");
break;
default:
thouValue = "";
break;
}
return thouValue;
}
`
Make your translator() method return a string which contains the final output.
So before the while statement in that method, declare a string such as
String result = null; and in the loop append the popped values to this variable like, result += stack.pop().
Now, the place where you call the translator(integer) method, do numeralInput.setText(translator(integer)) instead of translator(integer)
You need to make your TextView a class member and initialise it in your oncreate bundle, so that you can access the textview elsewhere in the activity.
TextView numeralInput;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_main);
numeralInput = (TextView) findViewById(R.id.textView);
convert.setOnClickListener(
new View.OnClickListener() {
public void onClick(View v) {
String intValue = numeralInput.getText().toString();
try{
int integer = Integer.parseInt(intValue);
if (integer > 0 && integer <= 4999){
translator(integer);
}else{
numeralInput.setText("Please enter an integer between 0 and 4,999.");
}
}catch(NumberFormatException e){
numeralInput.setText("Invalid input try again.");
}
}
}
);

Float variable != null not working

If (loanAmtValue!=null) is used..it throws an error ie."Operator != cannot be applied to float,null". Plzz sum1 come up with a solution to this prob.. The app crashes if no value is given in that field. So I was trying to use null condition check so that app doesn't crash even if no value is given.
public class SICalculatorActivity extends Activity implements View.OnClickListener {
private Button submit;
private Button submit2;
SeekBar sb;
TextView yrs;
EditText loanAmt;
EditText roi;
TextView siResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sicalculator);
final int years;
sb = (SeekBar)findViewById(R.id.set_years);
yrs = (TextView)findViewById(R.id.years);
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
yrs.setText(sb.getProgress()+" year(s)");
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
addButtonClickListener();
}
private void addButtonClickListener() {
submit = (Button)findViewById(R.id.button);
submit.setOnClickListener(this);
submit2 = (Button)findViewById(R.id.button2);
submit2.setOnClickListener(this);
}
#Override
public void onClick(View view) {
float loanAmtValue = 0;
float roiValue = 0;
double answer=0;
float y = sb.getProgress();
loanAmt = (EditText)findViewById(R.id.amt);
loanAmtValue = Float.parseFloat(loanAmt.getText().toString());
roi = (EditText)findViewById(R.id.roi);
roiValue = Float.parseFloat(roi.getText().toString());
if (loanAmtValue != null && roiValue != null){
case R.id.button:
answer = (loanAmtValue * roiValue * y) / 100;
siResult = (TextView) findViewById(R.id.result);
siResult.setText("Simple Interest for Amount Rs." + loanAmtValue + " and ROI " + roiValue + "% for "+y+" year(s) is = " + String.format("%.2f", answer));
loanAmt.setText("0");
roi.setText("0");
break;
}
}
else
{
siResult.setText("Please provide valid details");
}
}
}
float is a primitive data type and not an object. null check is used for objects.
For primitives you should use the default values check. For float the default value is 0.0f.
Read following:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
http://www.c4learn.com/java/java-default-values/
It looks like your problem is here :
loanAmtValue = Float.parseFloat(loanAmt.getText().toString());
This line will throw NumberFormatException if loanAmt doesn't contain a String that can be converted to a float.
You can check that the String is not empty before attempting to convert to float :
if (loanAmt.getText() != null && !loanAmt.getText().isEmpty()) {
loanAmtValue = Float.parseFloat(loanAmt.getText().toString());
}
This would still throw an exception if the user enters an invalid String, so you'll have to catch the exception :
if (loanAmt.getText() != null && !loanAmt.getText().isEmpty()) {
try {
loanAmtValue = Float.parseFloat(loanAmt.getText().toString());
catch (NumberFormatException ex) {
loanAmtValue = 0.0; // or some other default value
}
}
Null is used for objects. If an object is null, then this means this variable points to nowhere.
Obj a = null // a points nowhere
a = new Obj() // now a points to a place in the memory (a references an Obj object in the memory
And float is not an object type, it's a primitive type. But be carefull if you make comparison like: x == 0.0 (float comparison is not like comparison integers!).
To complete the answers, You cannot check if a float is null, like everybody said here. What You can do is, like "Der Golem" said check it if it is !=0, if You want to get sure that the value is not 0 (not the same like null!!!). BUT:
To prevent a NumberFormatException You also have to be sure, that Your catched value from the edit text field is a number. You can do it with TextUtils:
android.text.TextUtils.isDigitsOnly(CharSequence str).
In Your case, You should do it like this:
loanAmt = (EditText)findViewById(R.id.amt);
String loanAmtString = loanAmt.getText().toString();
if(android.text.TextUtils.isDigitsOnly(loanAmtString)){
loanAmtValue = Float.parseFloat(loanAmtString);
}
roi = (EditText)findViewById(R.id.roi);
String roiString = roi.getText().toString();
if(android.text.TextUtils.isDigitsOnly(roiString)){
roiValue = Float.parseFloat(roiString);
}
In my opinion, there are two ways to enforce user to enter only float values.
Using inputType for EditText
Checking entered text by a regular expression
Pattern ptrn = Pattern.compile("^\\d*\\.\\d*$");
String enteredText = ...;
if(ptrn.matcher(enteredText).matches()){
// try to parse the string here
}

How to pass data from a class and used in another class for calculation

i'm trying to do this feature where i calculate the calories needed in BMIcalculation class, then i created another class called CalorieIntake where in here i'll calculate the total calorie intake. (i do this by extends the BMIcalculation class.)
Then when i click on the 'Check' button, it should compare between this two value and show the interpretation. However i keep getting error at the 'interpretDiff(float diffValue)' part it mentioned it must return with a String value.
Here are my codes..pls help me to check where to problem is. Or is there a better way to do so? pls advice me. Thanks a lot..
public class CalorieIntake extends BMIcalculation {
TextView counter1;
Button compare;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.form_calorieintake2);
Button btn_calcIntake = (Button) findViewById(R.id.button_calcIntake);
btn_calcIntake.setOnClickListener(btnListener_calcIntake);
counter1 = (TextView) findViewById(R.id.textView_totalCalorieIntake);
Button compare = (Button) this.findViewById(R.id.checkIntake);
compare.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
try {
if ((!counter1.equals("")) && (!caloriesresult.equals("")))
{
TextView compareText = (TextView)findViewById(R.id.compareLabel);
EditText counter1E = (EditText) findViewById(R.id.textView_totalCalorieIntake);
EditText caloriesresultE = (EditText)findViewById(R.id.caloriesText);
float calorieIntake = Float.parseFloat(counter1E.getText().toString().trim());
float calorieNeed = Float.parseFloat(caloriesresultE.getText().toString().trim());
float diffValue = calDiff(calorieIntake, calorieNeed);
String calInterpretation = interpretDiff(diffValue);
compareText.setText("Difference of" + diffValue + " : " + calInterpretation);
}
}catch (Exception k)
{ System.out.println(k);
Toast.makeText(CalorieIntake.this, "Error", Toast.LENGTH_SHORT).show();
}
}
private String interpretDiff(float diffValue)
{
if (diffValue < 100)
{
return "Eat more";
}
}
private float calDiff(float calorieIntake, float calorieNeed) {
return (float) (calorieIntake - calorieNeed);
}
});
}
In interpretDiff, what happens if diffValue is not less than 100? You return nothing. However, java requires that you return something, as that is what the declaration of the method implies.
A solution would be:
private String interpretDiff(float diffValue)
{
if (diffValue < 100)
return "Eat more";
return "Eat less";
}
The else statement for if diffValue is not less than 100 is not necessary here because the second return statement is only called if diffValue >= 100 (since hitting a return statement exits out of the method).
With regards to the issue of the exception being thrown, and the Toast error being called, that can only happen as a result of the following code:
TextView compareText = (TextView)findViewById(R.id.compareLabel);
EditText counter1E = (EditText) findViewById(R.id.textView_totalCalorieIntake);
EditText caloriesresultE = (EditText)findViewById(R.id.caloriesText);
float calorieIntake = Float.parseFloat(counter1E.getText().toString().trim());
float calorieNeed = Float.parseFloat(caloriesresultE.getText().toString().trim());
float diffValue = calDiff(calorieIntake, calorieNeed);
String calInterpretation = interpretDiff(diffValue);
compareText.setText("Difference of" + diffValue + " : " + calInterpretation);
Assuming findViewById doesn't have an issue in it, the error is probably coming from getting the text of counter1E, caloriesresultE (if they are null). If neither of those are null, then check to make sure callDiff and interpretDiff don't have bugs in them. Finally, make sure compareText is not null.

Categories