Converting from String to BigDecimal to do math on currency - java

I am working on a project that requires some simple math to be performed on currency, however it arrives in the form of a String. I am new to Java/Android so I am looking for help in converting from a String to a data type appropriate to this operation. At first I thought Float was right but after reading elsewhere and introducing myself to the numbers class, it appears BigDecimal is correct. Am I on the right track? At this point I simply want to subtract the sum of payments from an initial invoice amount. I get the feeling this code is simple but clumsy and I suspect I am missing a great deal about the nuances of working with currency. How would you do it? All advice warmly appreciated!
// capture variables from sending activity
String invoiceAmt = getIntent().getStringExtra("invoiceAmt");
String paymentsSum = getIntent().getStringExtra("paymentsSum");
// convert strings to BigD's
BigDecimal amt = new BigDecimal(invoiceAmt);
BigDecimal sum = new BigDecimal(paymentsSum);
// Do the math
BigDecimal invDue = amt.subtract(sum);
// insert the value (back to string) into textView
TextView tvInvoiceDue = (TextView)findViewById(R.id.InvoiceDue);
tvInvoiceDue.setText(invDue.toString());

BigDecimal is a fine approach. So is using an int or a long to store cents. I've heard some people like Joda-Money but I've never used it myself.
See this question.
In the code you posted, make sure the Strings you are receiving don't have currency symbols in them.

Related

How display currency with Freemarker when using Longs

So let's say I have:
class Person
{
private long salary;
}
Where 5345273 would be equal to $53,452.73 (in other words the last two digits are the cents.
Is there a way to directly reference ${Person.salary} so that it displays the proper amount?
I did see that there are pre-defined formats such as Currency but there doesn't appear to be one if you use longs. I did see it was possible to create your own custom formatter but is this the only way? And if so is there anyone who already created one because I can't imagine I'm the only person using long to manage currency amounts. And also is that the correct solution?
Should be possible to convert the long to a double in the expression. Something like this: ${(Person.salary/100)?string.currency}

How can I make multiple operations work in calculator?

I made simple calculator for android for sake of learning but its buggy. All number keys just append respective number to TextView. Equals button does the job of adding/subtracting/divide/multiply. But the problem is, it can do only one at a time, if I mix plus operation with minus, it will crash. Here is code of equals button performing addition:
equals = (Button) findViewById(R.id.equals);
equals.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
result.getText();
String expression = (result.getText()).toString();
if(expression.contains("+")){
String[] numbers = expression.split("\\+");
String no1 = numbers[0];
String no2 = numbers[1];
Double numb1 = Double.valueOf(no1);
Double numb2 = Double.valueOf(no2);
Double added = numb1+numb2;
theresult = String.valueOf(added);
result.setText(theresult);
}
}
});
as you can see above, another problem arises. It cant handle more than one + sign, how can I make it work to add x amount of numbers? Sorry I am new to programming, instead of just making it work, I want to learn how it will work so please explain too if possible. Thanks.
This is best suited as a comment, I decided to put it as an answer just to not get it lost since there are already some answers.
Have a look at this question; the accepted answer might not be what you want because you want to learn, but there is an answer by boan that is possibly what you are looking for. I am not copying it here because it is already on S.O.
If its crashes then best idea is to post logcat error too.
Now the problem; you are separating the expression based on + only. so If you add - then the second part of the array would contain - also which can't be converted into double. Here you are getting the error.
So best idea is to separate the digit only part based on all the expressions such as +, -, * and /. Once all the expression has been separated then only you can convert the remaining values to string and perform the action based on respective expression.
You will have to write some code for all this.
Now resources that could help you. (Second is shorter approach)
Evaluating a math expression given in string form
How to parse a mathematical expression given as a string and return a number?

DecimalFormat weird behavior with pattern #####0.00 in Java

I am using below code snap to display float price value with two decimal points.
NumberFormat FORMAT = new DecimalFormat("#####0.00");
float myFloatValue =\\I am able to fetch this value dynamically
String finalPrice = FORMAT.format(myFloatValue);
// I am using this String (finalPrice) for export xml purpose.
It seems working fine normally, but I have noticed some examples(given below) where it is not working properly and produce the price with more than two decimal points. I am not able to replicate it again, I can see it in only log files.
Some examples output of finalPrice String : 0.10999966, 0.1800003, 0.45999908.
Can anybody help me to guess original value of myFloatValue from these outputs? So that it will help me to replicate the scenario and fix it.
The sporadic occurrence makes me wonder whether the DECIMAL_FORMAT is used in several threads concurrently. That is a no-no. However one would expect
wrong values too.
Maybe for good order also specify a fixed Locale (decimal point vs. comma, thousand separators).
And finally float or even double are not suited for financial software: those numbers are approximations.
BigDecimal price = new BigDecimal("9.99");
price = price.multiply(BigDecimal.TWO); // 19.98 exact
BigDecimal is a PITA for writing calculations, but keeps its precision.

Output Number, without digits after decimal place

ANDROID STUDIO HELP, THE VB.NET CODE ARE EXAMPLES - (SOLVED !!)
I'm coming from VB.NET (2+ Years).
Need help outputting Double variable, without digits after decimal place.
I understand that an integer is a number without any digits after the decimal place.
In Visual Basic or VB.NET, I can do this by doing this..
Dim Variable_Name_A as Decimal = 12.0123990110001
Variable_To_Hold_It = Decimal.Truncate(Variable_Name_A)
Outputs : 12
Val treats a String or TextBox as a Double.
So how can we do this in Java or for Android Studio?
Also, if you can answer but just one more question. How do you get rid of the negative symbol in Android Studio.. In VB.NET I can type the following code, to get rid of it.
Dim My_Variable_Name_A as Double = -12.00017
My_Variable_Name_B = Math.Abs(My_Variable_Name_A)
Outputs : 12.00017
So, I've taken a look at "Formater" for Android Studio. I've read countless posts that deals with digits after the decimal place. I don't understand any of it.
I DO NOT WANT ROUNDING.
In VB.NET, if I wanted to "Format" a number, we usually do something like this..
Dim Variable_Name_A as Double = 13.00192012334
Variable_Name_B = format(Variable_Name_A, "0.000")
Output : 13.002
I just need the whole number, before the decimal place for Android Studio, I don't want the numbers after the decimal place.
Also.. If you could.. WITHOUT ROUNDING.. Could you please tell me how to Format the number as well. Yes, with X number of digits after the decimal place.
Can you please help with my first question, and help me with the other questions if you can.
* So I figured it out.. *
EditText Millimeters_VARa = (EditText) findViewById(R.id.Millimeters_EditText_ID);
Double MM_Double = Double.parseDouble(Millimeters_VARa.getText().toString());
EditText Inches_VARa = (EditText) findViewById(R.id.Inches_EditText_ID);
DecimalFormat WholeNumber = new DecimalFormat("0");
DecimalFormat WholeAndThousandths = new DecimalFormat("0.000");
// Converts Millimeters to Inches.
Double MM_to_Inches_Convert = (MM_Double / 25.4);
Inches_VAR.setText(WholeNumber.format(MM_to_Inches_Convert));
Output Example : 2
Inches_VAR.setText(WholeAndThousandths.format(MM_to_Inches_Convert));
Output Example : 2.000
So, it seems it only works when finally outputting the value.
How would I store the formatted number or value in a Double Variable?
Ahh.. I figured it out. Like this?
* Storing a Formatted Number or Value as a Double *
Double TheWholeNumber = Double.parseDouble(WholeNumber.format(MM_to_Inches_Convert.toString()));
NOPE !! Doesn't work.. App Crashes.. Just keeping it simple, and formatting the number when finally outputting it with the setText.
But of course it rounds the last digit. So, now I'm gonna learn how to fix that.
PREVENTING FROM ROUNDING - SOLVED
public void FormatFunction(View v){
EditText EditText_VAR = (EditText) findViewById(R.id.EditText_A);
Double EditText_Double = Double.parseDouble(EditText_VAR.getText().toString());
TextView TextView_VAR = (TextView) findViewById(R.id.TextView_A);
DecimalFormat LOL = new DecimalFormat("0.0000");
LOL.setRoundingMode(RoundingMode.DOWN);
TextView_VAR.setText(LOL.format(EditText_Double));
VoilĂ 
That's how ya do it. I also understand now what the difference between using a pound sign "#", vs. using just a zero. The pound sign prevents trailing zeros.
The Class Name, FormatFuncion is called by a button Click.
<TextView
android:textSize="22sp"
android:id="#+id/TextView_A"
android:text="#string/OUTPUT_STRING"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"/>
<EditText
android:layout_width="200dp"
android:layout_height="60dp"
android:layout_marginTop="90dp"
android:id="#+id/EditText_A"
android:inputType="numberDecimal"/>
<Button
android:layout_width="150dp"
android:layout_height="60dp"
android:layout_below="#+id/EditText_A"
android:layout_marginTop="20dp"
android:text="#string/Format_String_A"
android:onClick="FormatFunction"/>
</RelativeLayout>
As you can clearly see.
This post should help anyone looking for the Answer to formatting a number, as well as how to prevent rounding. SOLVED.
Android programming is a little difficult. It takes much longer then programming in VB.NET using Visual Studio 2010. Apps for Windows OS. I could, lol, Correction.. "I HAVE" made apps a couple times already in VB.NET, and it sure as hell beats the snot out of Programing for Android. As far as the amount of time it takes to make an App for my $700+ (Android) Samsung Galaxy Note 4. I just hate.. Sorta.. typing my layout. It's time consuming. Also, in order to get things to line up correctly, as in making a button under another button, or on the right, left, etc. If you have multiple other objects, gotta say stuff like An Example : android:layout_toRightOf="#+id/EditText_A"
Just a pain in the A**, IMHO. But I love Coding for Android. Regardless if it takes some learning, and head scratching. Just much slower then VB.NET, by far.
1)Convert Double to String.
2)perform String.Split
3)join the two split parts again to a string
4)Parse String to Long
5)Wallah double without decimal
double dbNum=11112.1111;
String []dbStore=Double.toString(dbNum).split(".");
String strDBNum="";
for(String str:dbStore)
{
strDBNum+=str;
}
Long lDbNum=Long.parseLong(strDBNum);
Try this
double number = 1205.6358;
System.out.println("number : " + number);
DecimalFormat df = new DecimalFormat("###");
System.out.println("number (DecimalFormat) : " + df.format(number));
Java has this nifty little feature called a cast. Cast the Double to an int by sticking (int) in front of it
Double Variable_Name_A = 12.0123990110001;
System.out.println((int)Variable_Name_A);
What is essentially happening is Variable_Name_A is being converted to an int, thus dropping everything after the decimal. You can also keep Variable_Name_A as a double with the following:
Double Variable_Name_A = 12.0123990110001;
Double Variable_Name_A = (int)12.0123990110001;
System.out.println(Variable_Name_A);
1) There are a few ways to do this. You can either use DecimalFormat (docs found here or you can use a Cast (docs found here).
Casting is telling your program you want it to view one data type as another. In your case, you want a double to be seen as an int, which will drop anything beyond the decimal point.
double My_Variable_Name_A = -12.9345;
int casted = (int) My_Variable_Name_A;
DecimalFormat is a tool to specify exactly what you want to see in your output, though it outputs a String. It can format a large variety of things, and it's best to check out the documentation on it. It can get pretty in depth with the characters you might want to use.
DecimalFormat dfMy_Variable_Name_A = new DecimalFormat("#");
String newVariable = dfMy_Variable_Name_A.format(My_Variable_Name_A)
DecimalFormat("#") this is the part that decides the format. If you wanted "X number of places after the decimal", you would use DecimalFormat("#.###") for 3 places. If you wanted to make sure you had a comma to separate large numbers, you could use DecimalFormat("#,###") etc.
2) As far as the second half of your question, you can import Math and use the abs() method in Java to remove negative signs. Math.abs(My_Variable_Name_A);

BigDecimal precision above 1E22

for some reason I found myself coding some piece of software, that should be able to perfom some astronomic calculations.
While most of it will be about transfering the correct formula into Java, I found an annoying Problem right at the verry beginning of my "test how to calculate big numbers".
Well... Imagine the Sun (our Sun), which has a mass of (about and rounded, for more easy explaining) 10E30 kg. Ten with 30 following Zeros. All native datatypes are just unusuable for this. To mention: I KNOW that I could use 3000 to calculate things and just add trailing zeros in the output-view, but I hoped to keep it as precise as possible. So using short numbers will be my last resort only.
Comming to the Problem. Please have a look at the code:
BigDecimal combinedMass = new BigDecimal(1E22);
int massDistribution = 10;
Integer mD1 = massDistribution;
Integer mD2 = 100 - massDistribution;
BigDecimal starMass;
BigDecimal systemMass;
systemMass = combinedMass.divide(new BigDecimal("100")).multiply(new BigDecimal(mD1.toString()));
starMass = combinedMass.divide(new BigDecimal("100")).multiply(new BigDecimal(mD2.toString()));
System.out.println((systemMass).toEngineeringString());
System.out.println((starMass));
It will output 1000000000000000000000 and 9000000000000000000000, whats exactly what I did expect. But look at the combineMass Field. If I raise it to 1E23, the Output will change
I get 9999999999999999161139.20 and 89999999999999992450252.80...
So I know I could use jut BigInteger, because its more reliable in this case, but for the sake of precicion, sometimes the BigWhatEver may drop to something like 50.1258
Plus, I hope to get the 10.xE30 as output, whats only possible using bigDecimals.
I want to know: Is there no way avoidng this (that error appers above 1E23 for every value I tried), while keeping the ability to calculate Floating-Points? Should I cut the After-Decimal-Separator-Values for this Field to two digets?
And for something more to wonder about:
System.out.println(combinedMass.precision());
in relation with the code above will provide 23 for that case, but En+1 for most other values (Thats was when I grow really confused)
Thanks for advise.
You're using basic types without realizing it:
new BigDecimal(1E22);
Here, 1E22 is a primitive double, and you already lost precision by using it.
What you want is
new BigDecimal("10000000000000000000000");
or
new BigDecimal(10).pow(22);

Categories