decimalFormat to save as a double - java

I'm doing a project where I need to save some user input as a double, formatted to 4 decimal places. I can manage to get the string to have the right format, but parsing it to a Double breaks it. Here is an example of what i'm doing..
DecimalFormat format = new DecimalFormat("#.0000");
String example = "1.23";
Double num = Double.parseDouble(example);
String str = format.format(num);
Double num1 = Double.parseDouble(str);
System.out.println(num1);
this prints
1.23
when i'd like it to print
1.2300

You're confusing the number with the String representation of the number. These are two very different things. A floating point number has an accuracy, but it doesn't understand what display significant digits mean. It's like asking the abstract number 0 to know that 00 is.
To display the number correctly, use the formatter that you have already created:
System.out.println(format.format(num1));

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).

Parse Double to a specific format

I want to parse Double value to a specific format. I don't want it as a string.
I am trying
DecimalFormat format3DigitsAfterDecimal = new DecimalFormat("#0.000");
double d = 57;
Double.parseDouble(format3DigitsAfterDecimal.format(d));
This returns 57.0, I want 57.000 returned by format method in double.
Am I possibly asking wrong question ?
A double doesn't have a specific format.
Getting a Double value as 57.0 or 57.000 is the same for the computer but not for the user.
As a human, you don't read Double, but String representation of Double.
If you want a Double to be displayed with 3 decimal, you have to turn it to String using DecimalFormat
double d = 57.0;
NumberFormat numFormat = NumberFormat.getInstance();
numFormat.setMaximumFractionDigits(3);
numFormat.setMinimumFractionDigits(3);
System.out.println(numFormat.format(d));
You can't change the value of a decimal, but you can use NumberFormat to display it with three decimal places by setting minimum and maximum fraction digits like in the example above.

Double value with specific precision in java

I'm programming a simple java program. I need to get a string from input and divide it into two parts: 1-double 2-string.
Then I need to do a simple calculation on the double and send the result to the output with specific precision(4). It works fine, but there is a problem when the input is 0, then it doesn't work properly.
For example for these input, output will be:
1 kg
output:2.2046
3.1 kg
output:6.8343
But when the input is 0, the output should be 0.0000, but it shows 0.0 .
What should I do to force it to show 0.0000?
I read similar post about double precision, they suggest something like BigDecimal class, but I can't use them in this case,
my code for doing this is:
line=input.nextLine();
array=line.split(" ");
value=Double.parseDouble(array[0]);
type=array[1];
value =value*2.2046;
String s = String.format("%.4f", value);
value = Double.parseDouble(s);
System.out.print(value+" kg\n");
DecimalFormat will allow you to define how many digits you want to display. A '0' will force an output of digits even if the value is zero, whereas a '#' will omit zeros.
System.out.print(new DecimalFormat("#0.0000").format(value)+" kg\n"); should to the trick.
See the documentation
Note: if used frequently, for performance reasons you should instantiate the formatter only once and store the reference: final DecimalFormat df = new DecimalFormat("#0.0000");. Then use df.format(value).
add this instance of DecimalFormat to the top of your method:
DecimalFormat four = new DecimalFormat("#0.0000"); // will round and display the number to four decimal places. No more, no less.
// the four zeros after the decimal point above specify how many decimal places to be accurate to.
// the zero to the left of the decimal place above makes it so that numbers that start with "0." will display "0.____" vs just ".____" If you don't want the "0.", replace that 0 to the left of the decimal point with "#"
then, call the instance "four" and pass your double value when displaying:
double value = 0;
System.out.print(four.format(value) + " kg/n"); // displays 0.0000
System.out.format("%.4f kg\n", 0.0d) prints '0.0000 kg'
I suggest you to use the BigDecimal class for calculating with floating point values. You will be able to control the precision of the floating point arithmetic. But back to the topic :)
You could use the following:
static void test(String stringVal) {
final BigDecimal value = new BigDecimal(stringVal).multiply(new BigDecimal("2.2046"));
DecimalFormat df = new DecimalFormat();
df.setMaximumFractionDigits(4);
df.setMinimumFractionDigits(4);
System.out.println(df.format(value) + " kg\n");
}
public static void main(String[] args) {
test("0");
test("1");
test("3.1");
}
will give you the following output:
0,0000 kg
2,2046 kg
6,8343 kg
String.format is just makign a String representation of the floating point value. If it doesnt provide a flag for a minimum precision, then just pad the end of the string with zeros.
Use DecimalFormat to format your double value to fixed precision string output.
DecimalFormat is a concrete subclass of NumberFormat that formats
decimal numbers. It has a variety of features designed to make it
possible to parse and format numbers in any locale, including support
for Western, Arabic, and Indic digits. It also supports different
kinds of numbers, including integers (123), fixed-point numbers
(123.4), scientific notation (1.23E4), percentages (12%), and currency
amounts ($123). All of these can be localized.
Example -
System.out.print(new DecimalFormat("##.##").format(value)+" kg\n");

Convert string to decimal number with 2 decimal places in Java

In Java, I am trying to parse a string of format "###.##" to a float. The string should always have 2 decimal places.
Even if the String has value 123.00, the float should also be 123.00, not 123.0.
This is what I have so far:
System.out.println("string liters of petrol putting in preferences is " + stringLitersOfPetrol);
Float litersOfPetrol = Float.parseFloat(stringLitersOfPetrol);
DecimalFormat df = new DecimalFormat("0.00");
df.setMaximumFractionDigits(2);
litersOfPetrol = Float.parseFloat(df.format(litersOfPetrol));
System.out.println("liters of petrol before putting in editor: " + litersOfPetrol);
It prints:
string liters of petrol putting in preferences is 010.00
liters of petrol before putting in editor: 10.0
This line is your problem:
litersOfPetrol = Float.parseFloat(df.format(litersOfPetrol));
There you formatted your float to string as you wanted, but but then that string got transformed again to a float, and then what you printed in stdout was your float that got a standard formatting. Take a look at this code
import java.text.DecimalFormat;
String stringLitersOfPetrol = "123.00";
System.out.println("string liters of petrol putting in preferences is "+stringLitersOfPetrol);
Float litersOfPetrol=Float.parseFloat(stringLitersOfPetrol);
DecimalFormat df = new DecimalFormat("0.00");
df.setMaximumFractionDigits(2);
stringLitersOfPetrol = df.format(litersOfPetrol);
System.out.println("liters of petrol before putting in editor : "+stringLitersOfPetrol);
And by the way, when you want to use decimals, forget the existence of double and float as others suggested and just use BigDecimal object, it will save you a lot of headache.
Java convert a String to decimal:
String dennis = "0.00000008880000";
double f = Double.parseDouble(dennis);
System.out.println(f);
System.out.println(String.format("%.7f", f));
System.out.println(String.format("%.9f", new BigDecimal(f)));
System.out.println(String.format("%.35f", new BigDecimal(f)));
System.out.println(String.format("%.2f", new BigDecimal(f)));
This prints:
8.88E-8
0.0000001
0.000000089
0.00000008880000000000000106383001366
0.00
Use BigDecimal:
new BigDecimal(theInputString);
It retains all decimal digits. And you are sure of the exact representation since it uses decimal base, not binary base, to store the precision/scale/etc.
And it is not subject to precision loss like float or double are, unless you explicitly ask it to.
I just want to be sure that the float number will also have 2 decimal places after converting that string.
You can't, because floating point numbers don't have decimal places. They have binary places, which aren't commensurate with decimal places.
If you want decimal places, use a decimal radix.
litersOfPetrol = Float.parseFloat(df.format(litersOfPetrol));
System.out.println("liters of petrol before putting in editor : "+litersOfPetrol);
You print Float here, that has no format at all.
To print formatted float, just use
String formatted = df.format(litersOfPetrol);
System.out.println("liters of petrol before putting in editor : " + formatted);
Float.parseFloat() is the problem as it returns a new float.
Returns a new float initialized to the value represented by the specified String, as performed by the valueOf method of class Float.
You are formatting just for the purpose of display . It doesn't mean the float will be represented by the same format internally .
You can use java.lang.BigDecimal.
I am not sure why are you using parseFloat() twice. If you want to display the float in a certain format then just format it and display it.
Float litersOfPetrol=Float.parseFloat(stringLitersOfPetrol);
DecimalFormat df = new DecimalFormat("0.00");
df.setMaximumFractionDigits(2);
System.out.println("liters of petrol before putting in editor"+df.format(litersOfPetrol));

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.

Categories