Same decimal, different rounding results? [duplicate] - java

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

Related

How to get the value without round up/down in Java? [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
double d0 = Double.parseDouble("53.82233040000000557");
double d1 = Double.valueOf("53.82233040000000557");
output
d0 = 53.822330400000006
d1 = 53.822330400000006
Precision Numbers in Java
Class java.math.BigDecimal is better for handling numbers where precision matters (like monetary amounts), see BigDecimal VS double.
It could be used for geo-coordinates (latitude/longitude). Although practitionars argue that double is precise enough for lat./long. - since you don't want to locate something at nano-meter scale.
Example Code
If you need high precision and scale for your number, use BigDecimal like this:
BigDecimal decimalValue = new BigDecimal("53.82233040000000557");
System.out.println("as BigDecimal: " + decimalValue.toPlainString());
// prints exactly: 53.82233040000000557
Run this code online (IDE one): Double VS BigDecimal for high precision
Read more
Read more in a tutorial on Java: BigDecimal and BigInteger
If you need precision, you have to use a BigDecimal.
The answer is that you cannot. The values you are getting are the most accurate approximation to your values that can possibly be stored in a double. There is no possible way to get a more accurate, less rounded value stored in a double.
If you require that the answers are not rounded at all, therefore, you should not be using double. The data type you should be using instead is BigDecimal.

Print float with more decimal points [duplicate]

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.

Formatting floating numbers to certain length [duplicate]

This question already has answers here:
How to nicely format floating numbers to string without unnecessary decimal 0's
(29 answers)
Closed 9 years ago.
I want to limit my numbers to 7 significant figures (I believe this is known as significant digits in American English) with a maximum of 5 decimal places but I am ensure on how to do this.
I am currently using %-7.5f but this always prints 5 decimal places, even if those places aren't significant.
I.e. 3.75 becomes 3.75000
Here's some examples to try and further clarify what I am after:
3097.0 -> 3097
10.39596 -> 10.396
79.6103426 -> 79.61034
I.e. No leading or trailing 0s, 7 significant figures and at most 5 decimal places.
I'm trying to do this as I am working on upgrading an old program written in QBasic and this is how it formats it's floating point numbers when they are displayed. I want my Java code to output the numbers this way simply to make it easier to compare the results.
You can use DecimalFormat for this
double value1 = 10.39596;
double value2 = 79.6103426;
DecimalFormat df = new DecimalFormat("#.#####");
System.out.print(df.format(value1));
System.out.print(df.format(value2));
I suggest to use DecimalFormat for this purpose
new DecimalFormat("#.#####").format(d)
this pattern limits fractional part to max 5 digits
What about
DecimalFormat format = new DecimalFormat("#.#####");
System.out.println(format.format(79.6103426));

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

Java module operator [duplicate]

This question already has answers here:
Rounding Errors?
(9 answers)
Closed 10 years ago.
Why does this code print 2.4099999999999997, instead of just 2.41
public class Main
{
public static void main(String args[])
{
double d = 5.55%3.14;
System.out.println(d);
}
}
The problem is not the modulo operator, but rather the nature of floating point numbers. A double cannot hold the precise value of either 5.55, 3.14 or 2.41, so you get an approximate answer.
To understand this better, try to write down the value of 1/3 as a decimal, when you only have limited space on the paper to write it. You'll end up with something like 0.33333, which is an approximation of the actual value. The same happens to 5.55 when you write it in binary - it turns into 101.10001100110011001100110011... which gets cut off somewhere to fit the space of the double.
import java.text.DecimalFormat;
double d = 5.55%3.14;
DecimalFormat df = new DecimalFormat("#.##");
System.out.println( df.format( d ));
Add DecimalFormat
Edit:
You can also
double d = 5.55%3.14;
System.out.printf("%1$.2f", d);
Java double can have precision issues.
Why don't you try BigDecimal ?
the reason is that java doesn't do math the way we do. java uses binary numbers (from chapter 4 of Horstmann's big java book) so to a computer, 435 = 4 * 10^2 + 3 * 10^1 + 5 * 10^0
it does this because binary numbers (1 or 0) are easier to manipulate since switches in the computer are either on or off (1 or 0).
this results in occassional rounding issues. if you want to force it to round, then do things like use a decimal format, or if you just need the displayed value rounded you can use String.format or printf

Categories

Resources