Print float with more decimal points [duplicate] - java

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
I am experiencing a very strange behaviour when i am trying to print float number with more decimal points.
Float price = Float.valueOf("1602.72");
System.out.println(price); //prints 1602.72
outputValue = String.format("%.6f", price);
System.out.println(outputValue); //prints 1602.719971
I have also used below code but getting the same result
DecimalFormat df = new DecimalFormat("0.000000");
System.out.println(df.format(price)); //prints 1602.719971
I am expecting outputValue as 1602.720000 (6 digits after decimal with extra zeros)

A float is a binary representation of a number ( 1 / 2 ^^ ? )
like:
1/2^1 = 0.5,
1/2^2 = 0.25,
1/2^3 = 0.125,
1/2^4 = 0.0625, ...
The result renders from an addition of this binary numbers to find the closest match.

Never use floats or doubles for prices, floats and doubles are approximations, see: IEEE_754.
Have a look at BigDecimal instead.
Edit to be exact: use floats or doubles to represents decimals is an approximation.

That happens because floating point values are often imprecise for decimal fractions.
Basically, since floats are represented using negative powers of 2, some decimal values are very hard to represent accurately (e.g.: how do you write 0.3 as a sum of powers of two?).
You can try Float.valueOf("1602.720000") or Double.valueOf("1602.72") (better), but those will probably have the same issues.
Refer to this answer for a more detailed explanation.

Related

Round up double value in java [duplicate]

This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Closed 2 years ago.
I want to round up a double value in java. Always to round up the value in ispite that matematecally correct way, sometimes, is round down the value. For example:
value = 6.5817
I want to round up, keeping two decimals. So I need the value will be like this:
value = 6.59
The important thing here is always keep two decimals and always round up the second decimal if the value have more two decimals.
Have someone idea how I can to do this in java?
Since double values are inexact, e.g. it cannot store a number like 0.07 exactly, you need to use BigDecimal to help round up a double value, with the least probability of getting the wrong value.
To round to 2 decimals, use:
double value = 6.5817;
double roundedUp = BigDecimal.valueOf(value).setScale(2, RoundingMode.UP).doubleValue();
System.out.println(roundedUp); // prints 6.59
Note that this code prints 0.07 when value = 0.07, unlike e.g. Math.ceil(value * 100.0) / 100.0, which incorrectly prints 0.08.
Try the following:
double a = 6.5817;
Math.ceil(a * 100.0) / 100.0;

Same decimal, different rounding results? [duplicate]

This question already has answers here:
DecimalFormat with RoundingMode.HALF_UP
(2 answers)
Why does floating-point arithmetic not give exact results when adding decimal fractions?
(31 answers)
Closed 3 years ago.
Two decimal places are kept, the fractional part is the same, and the result is inconsistent
jdk1.8.0_162
DecimalFormat df = new DecimalFormat("##.00");
df.setRoundingMode(RoundingMode.HALF_UP);
System.out.println("1.985 ≈ " + df.format(1.985));
System.out.println("23.985 ≈ " + df.format(23.985));
1.985 ≈ 1.99
23.985 ≈ 23.98
The output is as above, and should be the same as the fractional part.
This is how floating point types work. They can be an approximation. The approximations for your two numbers are not the same since they are not the same numbers. The one number might be 1.985000000000001 and the other number might be 23.98499999999999 internally. See also here.
The issue you are seeing comes from specifying "23.985" in code, which when represented as a double is something slightly less.
A possible solution (if you absolutely need it to round the right way) is to use BigDecimal.valueOf to create the value. For example
//BigDecimal bd = BigDecimal.valueOf(23.985);
BigDecimal bd = new BigDecimal("23.985");
System.out.println("bd=" + bd);
System.out.println(df.format(bd)); // expected == actual

Using float and double for calculation, giving different results [duplicate]

This question already has answers here:
Why not use Double or Float to represent currency?
(16 answers)
Is floating point math broken?
(31 answers)
Closed 7 years ago.
I am working on a project where we are calculating prices of items with 8 places of decimal points.
But sometime calculation results are different.
I tried some samples but getting different calculation results:
public static void main(String[] args) {
double value1 = 0.999939f * 0.987792f;
double value2 = 0.999939 * 0.987792;
double value3 = (double)0.999939f * 0.987792f;
System.out.println("value 1 : "+ value1);
System.out.println("value 2: "+ value2);
System.out.println("value 3 : "+ value3);
}
Outputs are:
value 1 : 0.9877317547798157
value 2 : 0.9877317446880001
value 3 : 0.9877317839126931
These three are different results.
I am confused. Can anyone please clarify me what is happening here?
Thanks.
I went through some already answered, But I just want some ways where I can calculate with float and doubles only. otherwise I have to change many places. It will be painful.
Because of how floats and decimals are represented, the casts could be causing different results.
For: double value1 = 0.999939f * 0.987792f you are multiplying two floats and then casting it to a double. The resulting float representation is the one being converted to a double.
For: double value2 = 0.999939 * 0.987792; you are multiply two doubles and saving it in a double. This is time there is no casting so the representation never changes (ie. no potential data loss from change in data representation).
For: double value3 = (double)0.999939f * 0.987792f; you are multiplying a double that is casted from a float, times a float. Because of how the Java math works, that second float is probably also being casted to a double, so now you are multiplying two doubles that were once floats causing a third set of representations.
Because float and doubles have different precisions each of these will get a different result. For more info about floating point arithmetic, see here.
When you write a number with the "f" character, it is taken as float, meaning it is encoded with 32bits, whereas without it, it is a double, encoded with 64bits.
The more bits, the more accurately you will represent decimal numbers. This does not make a difference for number with few decimals, but in your case it is significant.
In conclusion, use exclusively double variables in your code.

Adding and subtracting doubles are giving strange results [duplicate]

This question already has answers here:
Retain precision with double in Java
(24 answers)
Closed 9 years ago.
So when I add or subtract in Java with Doubles, it giving me strange results. Here are some:
If I add 0.0 + 5.1, it gives me 5.1. That's correct.
If I add 5.1 + 0.1, it gives me 5.199999999999 (The number of repeating 9s may be off). That's wrong.
If I subtract 4.8 - 0.4, it gives me 4.39999999999995 (Again, the repeating 9s may be off). That's wrong.
At first I thought this was only the problem with adding doubles with decimal values, but I was wrong. The following worked fine:
5.1 + 0.2 = 5.3
5.1 - 0.3 = 4.8
Now, the first number added is a double saved as a variable, though the second variable grabs the text from a JTextField. For example:
//doubleNum = 5.1 RIGHT HERE
//The textfield has only a "0.1" in it.
doubleNum += Double.parseDouble(textField.getText());
//doubleNum = 5.199999999999999
In Java, double values are IEEE floating point numbers. Unless they are a power of 2 (or sums of powers of 2, e.g. 1/8 + 1/4 = 3/8), they cannot be represented exactly, even if they have high precision. Some floating point operations will compound the round-off error present in these floating point numbers. In cases you've described above, the floating-point errors have become significant enough to show up in the output.
It doesn't matter what the source of the number is, whether it's parsing a string from a JTextField or specifying a double literal -- the problem is inherit in floating-point representation.
Workarounds:
If you know you'll only have so many decimal points, then use integer
arithmetic, then convert to a decimal:
(double) (51 + 1) / 10
(double) (48 - 4) / 10
Use BigDecimal
If you must use double, you can cut down on floating-point errors
with the Kahan Summation Algorithm.
In Java, doubles use IEEE 754 floating point arithmetic (see this Wikipedia article), which is inherently inaccurate. Use BigDecimal for perfect decimal precision. To round in printing, accepting merely "pretty good" accuracy, use printf("%.3f", x).

Converting string to float in Java without round it [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Rounding in java Float.parseFloat
I want to convert strings to float i say:
System.out.println(Float.parseFloat("1553781.9829"));
Output:
1553782.0
I say:
System.out.println(Float.valueOf("1553781.9829"));
Output:
1553782.0
How to get Float without lossing precision?
use System.out.println(Double.parseDouble("1553781.9829")); instead
float has a limitation of smaller size (4 bytes) so it's not good for big decimals, double has the double size (8 bytes)
If you are looking for accuracy, I would suggest BigDecimal
This is just like normal wrapper class which provides methods for all your operations. And yes it takes argument as String as well.
BigDecimal bd = new BigDecimal("1553781.9829");
System.out.println(" bd :"+ bd); //prints the same value
URL : http://docs.oracle.com/javase/1.5.0/docs/api/java/math/BigDecimal.html
You cannot use float or double without a risk of losing precision. First of all their precision is limited, for float it is approx 7-8 decimal digits, for double ~16 digits. Apart from that Java floating points types are binary internally so they cannot store some decimal fractions without losing precision. If you really need exact decimal fractions use java.math.BigDecimal. Read "Effective Java" Item 48: "Avoid float and double if exact answers are required".
Instead of Float you can use Double
System.out.println(Double.valueOf("1553781.9829"));
System.out.println(Double.parseDouble("1553781.9829"));

Categories

Resources