Doing double - int in java - java

For example if I do this:
double decPart = 5.57 - 5;
System.out.println(decPart);
it returns 0.5700000000000003, instead of just 0.57. I can print it out properly using System.out.printf("%.2f", decPart), but that doesn't solve the problem (Note: the decimal part is not necessarily 2 decimal places). So for example if I try to do this:
System.out.println(1.0 - decPart);
it would return 0.4299999999999997
Can somebody please explain this behavior and how to fix it. Thanks in advance.

This is due to floating point imprecision. Floating-point numbers (float, double in Java) cannot represent some numbers exactly. If you're looking for absolute precision, look into BigDecimal.

Related

Trying to multiply double by int in java

I am trying to multiply 1207.87 by 10000 and expecting 12078700.0 but I am getting 1.2078699999999998E7
I understand that its related to precision mistake but how do i rectify this problem
EDIT:-
I simply want to remove the decimal
try this:
1207.87f * 10000
the result will be:
1.20787E7
This is because of float numbers representation.
You can:
round it Math.round(...)
or use BigDecimal if you need high precision.
More about What Every Computer Scientist Should Know About Floating-Point Arithmetic.
You need to do the CAST:
(int) 1207.87 * 10000
You cannot rectify this if you use double type. You can if you use BigDecimal.
Try to use decimal format like:
DecimalFormat f = new DecimalFormat("#0.00");
f.format(Double.valueOf(yourDouble));
Hope this can help you!
You can use formatted output as below:
double ans = 1207.87 * 10000;
System.out.printf("ans: %.0f\n", ans);
Output:
ans: 12078700
double are stored in exponental precision in java and many other languages. see IEEE754for more information about float, double and their variant
If you want a integer result, then cast your floating point number, or the result. If you want to just print a floating number in "ordinary notation", then you can use the class NumberFormat
NumberFormat formatter = new DecimalFormat("#0.00");
System.out.println(formatter.format(4.0));
example taken from here
finally you can use a fixed precision number with the class BigDecimal, but please take care that this is normally not hardware (FPU) accelerated so will slow down a lot your calculation, but will give you fixed error. That kind of number is especially used in simulation where error must be know
Simple way would be this one:
Double j = 1207.87;
int x = j.intValue();
System.out.println(x * 10000);

Weird decimal calculation in Java, potentially a bug?

I have weird decimal calculation that really surprise me, I have two big decimal number, one is a normal proce and the other one is an offer price. Then I want to calculate discount percentage and ceil it to the nearest integer.
Here are the code:
BigDecimal listPrice = new BigDecimal(510000);
BigDecimal offerPrice = new BigDecimal(433500);
int itemDiscount = (int)Math.ceil(((listPrice.longValue() - offerPrice.longValue()) / (float) listPrice.longValue()) * 100);
I expect it would set 15 as value of itemDiscount, but surprisingly it has 16, wow. Then i print each calculation to show in which statement is the problem, so i put System.out.println for each statement as below :
System.out.println(listPrice.longValue() - offerPrice.longValue()); //==> show 76500
System.out.println((listPrice.longValue() - offerPrice.longValue()) / (float) listPrice.longValue()); // ==> 0.15
System.out.println((listPrice.longValue() - offerPrice.longValue()) * 100 / (float) listPrice.longValue()); // ==> 15.000001
the problem is in above statement, istead of returning 15.0, it return 15.000001. And when i ceil it, it will of course return 16 instead of 15.
What is the explanation if this case? is this the way it is or it is a bug?
What is the explanation if this case? is this the way it is or it is a bug?
It is the way it is. It is not a bug.
You are doing the calculation using floating point types (float) and floating point arithmetic is imprecise.
I'm not sure what the best fix is here. Maybe doing the computation using BigDecimal arithmetic methods would give a better result, but it is by no means guaranteed that you won't get similar problems in this calculation with different inputs ...
However, I suspect that the real problem is that you should not be using ceil in that calculation. Even BigDecimal will give you rounding errors; e.g. if your computation involves dividing by 3, the intermediate result cannot be precisely represented using a base-10 representation.
The correct way to do calculations using Real numbers is to properly take account of the error bars in the calculation.
Try using the divide method directly from the BigDecimal class. If you are casting to a float then you are not using the benefit of BigDecimal .
http://www.roseindia.net/java/java-bigdecimal/bigDecimal-divide-int.shtml

Double manipulation trouble

Suppose n is a Double type variable .
double right=n-(Math.ceil(n)-1);
//Here I am trying to get the right part of the number.
Now if n=1234.78
then right=0.7799999999999727
why not .78?
and when
n=1234.89
then right=0.8900000000001
why not 89? and why not 9999... here instead of 000000....?
Now suppose I want to find the sum of digits in right..Like in my example for 1234.89 its 8+9=17 or 1234.781 its 7+8+1-16. So then ?what should I do?
But I can't do it using floating point arithmatic?Like
double temp=0.0;
while(right>0)
{
right=rigth*10;
temp=Math.floor(right);
right=right-temp;
suml+=temp;
}
in kind of a way I mentioned above?
I am new to java. please explain my problem. It would be a great help for me. Thank you.
Hey you can use the following code
double roundTwoDecimals(double d) {
DecimalFormat twoDForm = new DecimalFormat("#.##");
return Double.valueOf(twoDForm.format(d));
}
right=roundTwoDecimals(right);
System.out.println(right);
You will get desired result.
floating point works the same in almost all languages and you see the same issues. If you want the fractional part you should use.
double fract = n - (long) n;
I suspect the formula you are using will not work for negative numbers. (and is slower)
This can produce a rounding error as you have seen so you need to chose a level of precision. You might choose 2 or 6 digits. You can round the value when you calculate it but it's often simpler to round it when you print it.
System.out.printf("%.2f%n", fract);
This will print 0.78 and 0.89 as you expect.

Arithmetic expression calculates 6.135157E-6 instead of zero

I have the below code somewhere in my app
float private myMethod(float c){
result = (float) (c+273.15);
}
When "c" gets the value something like -273.1455 the result is something very near to zero like 0.0044.
But when it gets the value -273.15 i get this instead of zero: 6.1035157E-6
Why does this happen?
The problem is that 273.15 is a double, not a float, and neither of them can represent 273.15 exactly. However, since they have different precision they will round actually store different numbers. When the addition is done the c is converted to a double which will be able store the float representation of 273.15. So now you have two doubles with almost the same value and the difference will be non zero.
To get "more predictable" result, use 273.15f to ensure you have floats through the calculations. That should solve this problem but what you need to do is to read up on binary floating point arithmetics and how that differs from decimal arithmetic that we are taught in school.
Wiki on floating point is a good place to start.
Floating point calculations in computers are not accurate. You should read something about floating point arithmetics to prevent such errors.
The problem is not with the value, but with the display to the user.
I'm assuming you are converting it into a String. The way this is done is detailed in http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Double.html#toString(double)
To Display a correct value use the NumberFormat class http://docs.oracle.com/javase/1.4.2/docs/api/java/text/NumberFormat.html
Example :
NumberFormat formater = NumberFormat.getNumberInstance()
formatter.setMaximumFractionDigits(4);
formater.format(myMethod(-273.15))
Now you should get 0.

Subtraction of numbers double and long

In my JAVA program there is code like this:
int f_part = (int) ((f_num - num) * 100);
f_num is double and num is long. I just want to take the fractional part out and assign it to f_part. But some times f_part value is one less than it's value. Which means if f_num = 123.55 and num = 123, But f_part equals to 54. And it happens only f_num and num is greater than 100. I don't know why this happening. Please can someone explain why this happens and way to correct it.
This is due to the limited precision in doubles.
The root of your problem is that the literal 123.55 actually represents the value 123.54999....
It may seem like it holds the value 123.55 if you print it:
System.out.println(123.55); // prints 123.55
but in fact, the printed value is an approximation. This can be revealed by creating a BigDecimal out of it, (which provides arbitrary precision) and print the BigDecimal:
System.out.println(new BigDecimal(123.55)); // prints 123.54999999999999715...
You can solve it by going via Math.round but you would have to know how many decimals the source double actually entails, or you could choose to go through the string representation of the double in fact goes through a fairly intricate algorithm.
If you're working with currencies, I strongly suggest you either
Let prices etc be represented by BigDecimal which allows you to store numbers as 0.1 accurately, or
Let an int store the number of cents (as opposed to having a double store the number of dollars).
Both ways are perfectly acceptable and used in practice.
From The Floating-Point Guide:
internally, computers use a format (binary floating-point) that cannot
accurately represent a number like 0.1, 0.2 or 0.3 at all.
When the code is compiled or interpreted, your “0.1” is already
rounded to the nearest number in that format, which results in a small
rounding error even before the calculation happens.
It looks like you're calculating money values. double is a completely inappropriate format for this. Use BigDecimal instead.
int f_part = (int) Math.round(((f_num - num) * 100));
This is one of the most often asked (and answered) questions. Floating point arithmetics can not produce exact results, because it's impossible to have an inifinity of real numbers inside 64 bits. Use BigDecimal if you need arbitrary precision.
Floating point arithmetic is not as simple as it may seem and there can be precision issues.
See Why can't decimal numbers be represented exactly in binary?, What Every Computer Scientist Should Know About Floating-Point Arithmetic for details.
If you need absolutely sure precision, you might want to use BigDecimal.

Categories

Resources