Why does Java give 2 - (0.10 + 1.05) = 0.8499...? [duplicate] - java

This question already has answers here:
Floating point arithmetic not producing exact results [duplicate]
(7 answers)
Floating point comparison [duplicate]
(5 answers)
Closed 9 years ago.
I'm fairly new to java but have some experience of coding (mostly PHP and some C++).
I'm having some trouble with calculations in my program. When I run the following code:
public class Test {
public static void main(String[] args) {
double number = 2 - (0.10 + 1.05);
System.out.println( number );
if( number < 0.85 ) System.out.println("to small");
}
}
My output is as follows:
run:
0.8499999999999999
to small
BUILD SUCCESSFUL (total time: 0 seconds)
I'm expecting 2 - ( 0.10 + 1.05 ) to be equal to 0.85 but for some reason it's not. Does anyone know why it would behave like this?
I'm using netbeans to code version 7.3.1 and jdk7u25 on Windows 8 if that is important. If there is anything else I should add please tell.
/Chris

That is because floating point numbers cannot represent all numbers in its range precisely, but takes something close. See:
http://introcs.cs.princeton.edu/java/91float/
That is also why you should never use float or double for storing monetary values.

Floating points numbers are in exponential form. There consists of mantissa and exponent field. Because of binary coding they do not cover exact numbers, but are close to them.
To have exact numbers use BigDecimal - http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html .

Because floating point numbers don't work like you think they do. In a nutshell, not all numbers can be precisely expressed in floating-point format, so you will see things like this when you use floating point data types.

Related

Dealing with innaccuracy from double arithmetic? [duplicate]

This question already has answers here:
Large Numbers in Java
(6 answers)
Closed 5 years ago.
I've written a method that tests whether a number is prime or not. To maximise the range of numbers that the user can input, I wanted to use doubles. The issue is, after testing it on a very large prime, like 40 digits or so, my method returns false (I've already tested the logic with an int version, and it works just fine as far as I can tell).
Here is my code:
public static boolean isPrime(double number) {
double sqrt = Math.sqrt(number);
for(double i = 2; i<= sqrt; i++) {
if(number%i == 0) {
return false;
}
}
I know the reason it's not working at very high numbers is because of the accuracy error, but is there around this?
I know the reason it's not working at very high numbers is because of the accuracy error, but is there around this?
Yes. Use BigInteger.
Note that long would be better than double, since long can represent all integers up to 2^63 - 1 precisely. By contrast, with double you start losing precision at 2^53 + 1. However neither of these types are suitable for 40 (decimal) digit numbers.
BigInteger arithmetic is significantly slower, but the you will be able to go up to (at least) 2^Integer.MAX_VALUE ... provided that you have enough heap space.

How to display values only upto 2 decimal places double in java [duplicate]

This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Closed 6 years ago.
I am doing this Java question :
Jalaj purchased a table for Rs.200.4 and due to some scratches on its
top he had to sell it for Rs.176.5. Find his loss and loss%.
LOSS : Cost Price - Selling Price
LOSS% : (LOSS/Cost Price)*100
a. Declare four double variables i.e. costprice, sellingPrice, loss,
lossPercentage
b. Assign 200.4 to costPrice and 176.5 to sellingPrice.
c. Print loss and lossPercentage according to the given formulas like:
823.67 8.23 d.
For printing upto two decimal places use
System.out.printf("%.2f\n", loss);
Note:
output for both should be upto two decimal places
Output should be displayed in two different lines
My code:
/*Write your code here */
import java.util.Scanner;
class bkws{
public static void main(String args[]){
double costPrice,sellingPrice,loss,lossPercentage;
costPrice=200.4;
sellingPrice=176.5;
loss=costPrice-sellingPrice;
lossPercentage=(loss/costPrice)*100;
System.out.print("%.2f",loss);
System.out.println("%.2f",lossPercentage);
}
}
Now I am thinking of using Math.round but for rounding off to 2 decimal places it should be:
Math.round(number*100)/100;
But it is giving error and I also want to know that if there is any easy way to round off to n decimal places without using Math.round in Java.
double costPrice,sellingPrice,loss,lossPercentage;
costPrice=200.4;
sellingPrice=176.5;
loss=costPrice-sellingPrice;
lossPercentage=(loss/costPrice)*100;
System.out.println(String.format("%.2f", loss));
System.out.println(String.format("%.2f", lossPercentage));
OR
double costPrice,sellingPrice,loss,lossPercentage;
costPrice=200.4;
sellingPrice=176.5;
loss=costPrice-sellingPrice;
lossPercentage=(loss/costPrice)*100;
loss = (int)Math.round(loss * 100)/(double)100;
lossPercentage = (int)Math.round(lossPercentage * 100)/(double)100;
System.out.println(loss);
System.out.println(lossPercentage);
printf with an f for format at the end is a different method to print or println
For printing upto two decimal places use
System.out.printf("%.2f\n", loss);
BTW: Using %n inside a format string is a better choice than \n as %n is platform independent.
You don't need to round the result if you using rounding in the format.
The real lesson to be learned here: all of the things you need are clearly documented.
You can start here to learn about System.out; to then go forward and understand how such PrintStreams work in general.
You will also find nice explanations there how those "format" patterns actually work.
In other words: the one big thing about using Java is that A) there is a library method for almost everything and B) all of that is documented with extraordinary quality. There is no need to speculate; and heck: not even a need to ask other folks for such information. It is all there, waiting for you.

Solving A math equation using Java [duplicate]

This question already has answers here:
Why does division result in zero instead of a decimal?
(5 answers)
Closed 8 years ago.
I have hit a snag in my program when this calculates I get result of 0.0
y = 1/6*Math.pow(x,3)+1/2*Math.pow(x,2)-1/3*x;
I have tried writing the equation in chunks so I can add the results up after calculation but the result just keeps ending up being 0.0 and I don't know why. Is this a syntactical error or is there a rule that I'm missing about java?.
When you divide two integers Java truncates the result to an integer. If you want a fractional result you need to use floating point numbers. 1/2 is 0; 1.0/2.0 is 0.5.
y = 1.0/6.0*Math.pow(x,3) + 1.0/2.0*Math.pow(x,2) - 1.0/3.0*x;
y = 1/6*Math.pow(x,3)+1/2*Math.pow(x,2)-1/3*x;
Here you are doing division of two integers, which would result in 0. Make one/both of the values to decimal (1.0/6.0 etc) and then try this. It should give the correct result. The reason is that, 1/6 will be corrected to the closest integer value, which is 0.

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