Parse double from JFormattedTextField - java

I've got a bug or something. I have a method that saves an article, like this:
class SaveArticleListener implements ActionListener {
//....
String s = textArticlePrice.getText().replace(',','.').replaceAll("\\s","");
double price = Double.parseDouble(s);
//....
}
Where textArticlePrice is a JFormattedTextField which configured like:
NumberFormat priceFormat = NumberFormat.getNumberInstance();
priceFormat.setMaximumFractionDigits(2);
priceFormat.setMinimumFractionDigits(2);
textArticlePrice = new JFormattedTextField(priceFormat);
textArticlePrice.setColumns(10);
And in the parseDouble method I'm getting every time:
java.lang.NumberFormatException: For input string: "123 456 789.00"
So replace works with a dot, but not with whitespace... Why?

You'd be better off using your NumberFormat to parse the String. Keep a reference to priceFormat, and then use
double price = priceFormat.parse(textArticlePrice.getText()).doubleValue();
The formatter that's being used to display the number is the same one then used to turn it back into a double so you know it's going to be parsing it in a compatible way.
Best of all is
double price = ((Number) textArticlePrice.getValue()).doubleValue();
which should work without any need for conversion if you've set your JFormattedTextField up properly. (The getValue() call returns an Object, so you need to cast it. It might return a Double or a Long, depending on what's in the text field, so the safe way to get a double out of it is to treat it as a Number, which is the supertype of both, and invoke its .doubleValue() method.)
Writing something that converts it into something that can be parsed by Double.parseDouble() is really not the right way to go because it's too fragile if the formatting of your text field changes later on.

Regarding your question" why doesn't it work with white spaces". White spaces are chars just like a,l,#,?,¡, but it only recognises ,12345, numbers together as a number, you cant make an int variable 'int number = 1 234; Its the same with parsing. Rather try,
s = s.replace(',','.');
s = s.replace(" ","");
Price = Double.parseDouble(s);
Assuming that '123 456 789.00' is one number.
please comment if this helped.

I did this now, it worked fine
String strNumber = "1 2 3 4 5 6.789";
double DblNumber = Double.parseDouble(strNumber);
System.out.Println(DblNumber);// this displays the number if your IDE has an output window

Related

Error: while trying to format decimal output in Java

I am writing this program as an assignment for school. The program takes input in the form of 'sex' and 'age' from the user, and gives back the average age of all men and/or women.
The program has worked fine up until my mom beta tested it and we found a problem by happenstance. If by any chance the user were to input a number of individuals where the sum of their ages is not divisible by the number of individuals inputted, the output will give an answer with 15 decimal places.
For example if I input 3 men with the ages 98, 1 and 1, the program divides 100 by 3 and I get the output:
33.333333333333336.
So I took to SO to find a solution to this problem, and found this which I implemented in my program like below so that it would trim down the answer to a maximum of 3 decimal places:
/*
This method takes two values. The first value is divided by the second value to get the average. Then it trims the
answer to output a maximum of 3 decimal places in cases where decimals run amok.
*/
public static double average (double a, double b){
double d = a/b;
DecimalFormat df = new DecimalFormat("#.###");
return Double.parseDouble(df.format(d));
I wrote the code in the bottom of my program, in its own method, which I call in the main method at lines 76 and 77:
// Here we calculate the average age of all the people and put them into their respective variable.
double yAverage = average(yAge, men);
double xAverage = average(xAge, women);
However. I get this error message when I try to run the program, and I don't understand the error message. I tried googling the error, but found nothing.
Please keep in mind that I'm a beginner, and I need as simple an answer as anyone can give me.
Thank you in advance!
The problem is that DecimalFormat honors you Locale setting, formatting the number according to your language setting.
E.g. in US English the result is 33.333, but in Germany the result is 33,333.
However, Double.parseDouble(String s) is hardcoded to only parse US English formatting.
A few options to fix it:
Don't round the value. Recommended
Use a DecimalFormat wherever the value needs to be displayed, but keep the full precision of the value itself.
Force DecimalFormat to use US English formatting symbols.
DecimalFormat df = new DecimalFormat("#.###", DecimalFormatSymbols.getInstance(Locale.US));
Use the DecimalFormat to re-parse the value.
DecimalFormat df = new DecimalFormat("#.###");
try {
return df.parse(df.format(d)).doubleValue();
} catch (ParseException e) {
throw new AssertionError(e.toString(), e);
}
Don't convert to/from string to round to 3 decimal places.
Use Math.round(double a).
return Math.round(d * 1000d) / 1000d;
Use BigDecimal (and stick with it). Recommended
return BigDecimal.valueOf(d).setScale(3, RoundingMode.HALF_UP);
Use BigDecimal (temporarily).
return BigDecimal.valueOf(d).setScale(3, RoundingMode.HALF_UP).doubleValue();
Try this code
public static double average(double a, double b) {
double d = a / b;
DecimalFormat df = new DecimalFormat(
"#.###",
DecimalFormatSymbols.getInstance(Locale.ENGLISH)
);
return Double.parseDouble(df.format(d));
}
You're using a formatting with the point as decimal separator ("#.###"). Depending on the location where you run your program, the Java runtime uses a different localisation setting, e.g. in Germany, where a comma is used as decimal separator.
When you use new DecimalFormat("#.###") the default locale is used to interpret the string #.### which may work in some places, but won't in others. Luckily, there is another constructor for DecimalFormat where you can specify what symbols should be used. By using DecimalFormatSymbols.getInstance(Locale.ENGLISH) as second parameter you specify that you want the English formatting conventions ("." as decimal separator, "," for thousands).

Double with specific format and two decimals

I'm trying to format the numbers to look like a certain way.
So, I have like the number 1007,2, and I want it to look like 1 007,20
This has two factors needed:
Thousands format
Two decimal places
I have a code that sets the thousands format:
Double total_value = Double.valueOf(1007,2);
String formatedValue = NumberFormat.getNumberInstance(Locale.CANADA_FRENCH).format(total_value);
And the output is:
1 007,2€
And I have the code for the two decimal places:
Double total_value = Double.valueOf(1007,2);
String formatedValue = String.format("%.2f", total_value);
The problem is, for using this two format methods at the same time they get always problems, because the two of them return Strings, and both need to receive the values for formatting in Double.
If I receive one in String, when I try to parse the String to Double like String value = Double.parseDouble(formatedValue);or String value = Double.valueOf(formatedValue) they always get an error. I've already tried the DecimalFormat to but it returns a String too.
So, I dont know how to do to conjugue the two methods to work together!
If you have any idea please comment it :)
You don't want to combine NumberFormat and String.format().
You can further configure your NumberFormat object to tell it to use two decimal places:
NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.CANADA_FRENCH);
numberFormat.setMinimumFractionDigits(2);
assertThat(numberFormat.format(1007.2), is("1 007,20"));
(and possibly setMaximumFractionDigits() etc., depending on your needs -- see the Javadoc)
Take care - NumberFormat.format() is not thread-safe.
Alternatively you can use String.format(locale, format, args):
assertThat(String.format(Locale.CANADA_FRENCH, "%,.2f", 1007.2), is("1 007,20"));
The , flag in the format tells the formatter to use a thousands-separator, and the locale tells it that the separator is a space.
After setting the thousand format you could do someting like:
String[] splitter = formatedValue.split("\\,");
int decimalDigits = 0;
if (splitter.length > 1) {
formatedValue = splitter[1].length();
} else {
formatedValue += ",";
}
for (int i = 0; i < 2 - decimalDigits; i++) {
formatedValue += "0";
}
I have not tested this, and it is not the really pretty, but i am using something similar for the english format.
To make sure you have only two decimal digits you should probably round your total value at the beginning.

Formating big numbers in Java

I have an edittext with a maxlength
My question is...
How can I display the value of a bigger number than the maxlenght like the windows calc??
Example:
1.34223423423434e+32
I want this with the edittext maxlength
EDIT: I want this for display and store numbers without having problems with math operations if it's possible
Thanks
This is what the BigInteger class (or BigDecimal, for non-integers) is for.
These classes store numbers with arbitrary precision, and allow for standard arithmetic operations. You can get the exact value of the number as a string, and then format that as you wish (e.g. trimming the length).
(Note that while it may seem like you can use these classes with a NumberFormat instance, this is not recommended as accuracy will be silently lost if the number doesn't fit into a double.)
Here's an example of using it:
// Create a BigDecimal from the input text
final String numStr = editText.getValue(); // or whatever your input is
final BigDecimal inputNum = new BigDecimal(numStr);
// Alternatievly you could pass a double into the BigDecimal constructor,
// though this might already lose precison - e.g. "1.1" cannot be represented
// exactly as a double. So the String constructor is definitely preferred,
// especially if you're using Double.parseDouble somewhere "nearby" as then
// it's a drop-in replacement.
// Do arithmetic with it if needed:
final BigDecimal result = inputNum.multiply(new BigDecimal(2));
// Print it out in standard scientific format
System.out.println(String.format("%e", result));
// Print it out in the format you gave, i.e. scientific with 14dp
System.out.println(String.format("%.14e", result));
// Or do some custom formatting based on the exact string value of the number
final String resultStr = result.toString();
System.out.println("It starts with " + result.subString(0, 3) + "...");
I'm not sure exactly what format you wanted for output, but whatever it is you should be able to manage it with BigDecimals as the backing store.

How can I format a String number to have commas and round?

What is the best way to format the following number that is given to me as a String?
String number = "1000500000.574" //assume my value will always be a String
I want this to be a String with the value: 1,000,500,000.57
How can I format it as such?
You might want to look at the DecimalFormat class; it supports different locales (eg: in some countries that would get formatted as 1.000.500.000,57 instead).
You also need to convert that string into a number, this can be done with:
double amount = Double.parseDouble(number);
Code sample:
String number = "1000500000.574";
double amount = Double.parseDouble(number);
DecimalFormat formatter = new DecimalFormat("#,###.00");
System.out.println(formatter.format(amount));
This can also be accomplished using String.format(), which may be easier and/or more flexible if you are formatting multiple numbers in one string.
String number = "1000500000.574";
Double numParsed = Double.parseDouble(number);
System.out.println(String.format("The input number is: %,.2f", numParsed));
// Or
String numString = String.format("%,.2f", numParsed);
For the format string "%,.2f" - "," means separate digit groups with commas, and ".2" means round to two places after the decimal.
For reference on other formatting options, see https://docs.oracle.com/javase/tutorial/java/data/numberformat.html
Given this is the number one Google result for format number commas java, here's an answer that works for people who are working with whole numbers and don't care about decimals.
String.format("%,d", 2000000)
outputs:
2,000,000
Once you've converted your String to a number, you can use
// format the number for the default locale
NumberFormat.getInstance().format(num)
or
// format the number for a particular locale
NumberFormat.getInstance(locale).format(num)
I've created my own formatting utility. Which is extremely fast at processing the formatting along with giving you many features :)
It supports:
Comma Formatting E.g. 1234567 becomes 1,234,567.
Prefixing with "Thousand(K),Million(M),Billion(B),Trillion(T)".
Precision of 0 through 15.
Precision re-sizing (Means if you want 6 digit precision, but only have 3 available digits it forces it to 3).
Prefix lowering (Means if the prefix you choose is too large it lowers it to a more suitable prefix).
The code can be found here. You call it like this:
public static void main(String[])
{
int settings = ValueFormat.COMMAS | ValueFormat.PRECISION(2) | ValueFormat.MILLIONS;
String formatted = ValueFormat.format(1234567, settings);
}
I should also point out this doesn't handle decimal support, but is very useful for integer values. The above example would show "1.23M" as the output. I could probably add decimal support maybe, but didn't see too much use for it since then I might as well merge this into a BigInteger type of class that handles compressed char[] arrays for math computations.
you can also use the below solution
public static String getRoundOffValue(double value){
DecimalFormat df = new DecimalFormat("##,##,##,##,##,##,##0.00");
return df.format(value);
}
public void convert(int s)
{
System.out.println(NumberFormat.getNumberInstance(Locale.US).format(s));
}
public static void main(String args[])
{
LocalEx n=new LocalEx();
n.convert(10000);
}
You can do the entire conversion in one line, using the following code:
String number = "1000500000.574";
String convertedString = new DecimalFormat("#,###.##").format(Double.parseDouble(number));
The last two # signs in the DecimalFormat constructor can also be 0s. Either way works.
Here is the simplest way to get there:
String number = "10987655.876";
double result = Double.parseDouble(number);
System.out.println(String.format("%,.2f",result));
output:
10,987,655.88
The first answer works very well, but for ZERO / 0 it will format as .00
Hence the format #,##0.00 is working well for me.
Always test different numbers such as 0 / 100 / 2334.30 and negative numbers before deploying to production system.
According to chartGPT
Using DecimalFormat:
DecimalFormat df = new DecimalFormat("#,###.00");
String formattedNumber = df.format(yourNumber);
Using NumberFormat:
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setGroupingUsed(true);
String formattedNumber = nf.format(yourNumber);
Using String.format():
String formattedNumber = String.format("%,.2f", yourNumber);
Note: In all the above examples, "yourNumber" is the double value that you want to format with a comma. The ".2f" in the format string indicates that the decimal places should be rounded to 2 decimal places. You can adjust this value as needed.

Java Double to String conversion without formatting

I have the number 654987. Its an ID in a database. I want to convert it to a string.
The regular Double.ToString(value) makes it into scientific form, 6.54987E5. Something I dont want.
Other formatting functions Ive found checks the current locale and adds appropriate thousand separators and such. Since its an ID, I cant accept any formatting at all.
How to do it?
[Edit] To clarify: Im working on a special database that treats all numeric columns as doubles. Double is the only (numeric) type I can retrieve from the database.
Use a fixed NumberFormat (specifically a DecimalFormat):
double value = getValue();
String str = new DecimalFormat("#").format(value);
alternatively simply cast to int (or long if the range of values it too big):
String str = String.valueOf((long) value);
But then again: why do you have an integer value (i.e. a "whole" number) in a double variable in the first place?
Use Long:
long id = 654987;
String str = Long.toString(id);
If it's an integer id in the database, use an Integer instead. Then it will format as an integer.
How about String.valueOf((long)value);
What about:
Long.toString(value)
or
new String(value)
Also you can use
double value = getValue();
NumberFormat f = NumberFormat.getInstance();
f.setGroupingUsed(false);
String strVal = f.format(value);
If what you are storing is an ID (i.e. something used only to identify another entity, whose actual numeric value has no significance) then you shouldn't be using Double to store it. Precision will almost certainly screw you.
If your database doesn't allow integer values then you should stored IDs as strings. If necessary make the string the string representation of the integer you want to use. With appropriate use of leading zeros you can make the alphabetic order of the string the same as the numeric order of the ints.
That should get you round the issue.
What about Long.toString((long)value) ?
double d = 56789;
String s = d+"";

Categories