This question already has answers here:
Floating point arithmetic not producing exact results [duplicate]
(7 answers)
Closed 9 years ago.
I'am confused. I'm trying to get an int value:
Integer ord = new Double(33 / (-2 * 1.1)).intValue();
Expectation: -15
Output: -14
What's wrong?
When I try:
Double d = 33 / (-2 * 1.1);
Output: -14.999999999999998
Any ideas? Thanks in advance!
.intValue() will trunc the frarctinal part so you can use Math.ceil(), Math.floor() or you can use Math.round() to approximate it to the nearest value
Integer result = (int) Math.round(new Double(33/(-2*1.1))); //-15
Integer result = (int) Math.floor(new Double(33/(-2*1.1))); //-15
Integer result = (int) Math.ceil(new Double(33/(-2*1.1))); //-14
You can see that Math.ceil() give us 14 because this is a negative number -14>-15 so the ceil of -14.9999 is -14 and the inverse apply on Math.floor()
intValue() doesn't do round but truncate.
The double output of -14.999999999999998 has it's origin in the precision of the double type. A floating point number is always a sum of 2^n numbers. The result is that not all numbers can be represented precisely, even with double.
Your integer example returns -14 because the integer value of -14.999999999999998 is -14. There is no rounding when getting the integer value. It is just cut of at the decimal point.
For rounding use either Math.ceil() for rounding up, Math.floor() for rounding down or Math.round() for general rounding.
When getting the int value of a double, java isn't doing any round up or down for you. It just omits the decimals.
What you want to do is to use the Math.round(double) to get the value you are expecting.
I believe the java doc for Math.round() says it will return a long value, but if you are sure that your result never will be larger than the maximum int value, then you can cast it to an int.
int result = (int) Math.round(new Double(33/(-2*1.1)));
Warning: Using the authority argument :P
Josh Bloch has an entire item in his Effective Java book against using double or float when aiming for accuracy. In my life, working with currency, for example, I have had the best results working with BigDecimal
You are using 32 bit float so losing a lot of precision. Try Double d = 33 / (-2 * 1.1d);
And, as everybody say, better round than truncate.
Related
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 8 years ago.
double test = 1029 / 9.8; // = 104.99999...
int inttest1 = (int) test; // 104
int inttest2 = (int)Math.floor(test); // 104
double testtt = 9.8 * 105; // 1029.0
1029 / 9.8 equals 105
but Java returns 104.9999...
More serious problem is integer casing result is 104, not 105
Why this happens and how can I avoid this result?
There are an infinite number of numbers, even in the limited range represented by Java. That's because mathematically, if you give me any two distinct numbers, I can average them to get a number between them. No matter how close they are.
And there are only a limited number of bits available to represent those numbers.
Hence, something has to give. What gives is the precision of the numbers. Not all numbers can be represented exactly, so some (the vast majority actually) are approximations.
For example, 0.1 cannot be represented exactly with IEEE754 encoding, even with a billion bits available to you.
See this answer for more information on the inherent imprecision of limited-storage floating point numbers.
Casting to an int implicitly drops any decimal. No need to call Math.floor() (assuming positive numbers)
To avoid this behavior use BigDecimal;
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
Standard floating point variables are in binary floating point. Many decimal floating point values (which are the ones you type in your code) have no exact representation in binary floating point. So it isn't doing the calculation with the exact numbers you entered but with some values very close to it. You can use Math.round to round the result to the precision you need and most likely the small error will disappear.
If you really need exact decimal calculation use BigDecimal but note that it is much slower.
When I perform simple math in java with doubles and other number data types, the double values seem to randomly vary a bit from the supposed result, which might be 5,59999999997 or 6,0000000002 or something. When I cast to int, the double value is obviously rounded down to the next whole number. Does this mean the double could be both 5 or 6? Or does that "5,999999999997" still count as 6 though which would be depending on the binary float value? If not, is there a way to let the negative vary be rounded up, but not lower values from 5,5 to 5,999999999996?
I mean, I dont really want to round the value as described in my last sentence. I'd like to always round down to the next whole number, but I don't want to cause an extra decrement due to wrong double math results.
Converting a double to an int always rounds down. You can round to the nearest whole integer via Math.round(double). The double is varying from what you expect because of floating point error.
If you want to round, you can use the round() method.
double d = 6 +/- some small error
long l = Math.round(d);
Or you can add 0.5 for positive numbers
long l = (long) (d + 0.5);
or
long l = (long) (d + (d < 0 ? -0.5 : 0.5));
I'm not sure I understand the question. Usually when you cast a double to int you add 0.5 to have a nice round.
From the Java Language Specification:
The Java programming language uses round toward zero when converting a floating value to an
integer (§5.1.3), which acts, in this case, as though the number were truncated, discarding
the mantissa bits. Rounding toward zero chooses at its result the format's value closest to
and no greater in magnitude than the infinitely precise result.
So 5,999999999997 when casted to an int will 5 and 6,0000000002 will be 6. If I understand what you are asking with having negative versions of the values (e.g. -5.97), I fail to see how
Math.round() does not suffice you. -6,0000000002 will be rounded to -6 as will -5,999999999997 and every other value above (but not including) -5.5.
This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Closed 9 years ago.
I just wanted to ask a quick question regarding the Math.round method. I'm trying to compute the division of two ints into a double. The equation looks like this: 199/39. When I do this it returns 5.0 as the answer. I know the answer should be 5.1 with some more decimals. I have been told to use the Math.round method to round it to the nearest tenth, but I have no idea how to accomplish this. Should I change that double variable to a int and make it int/int=int? I'm not sure how Math.round even works to get 5.1 as I've read it only rounds to the nearest integer not decimal point. Any help would be fantastic.
P.S This is homework, but I ask only because I can't find any information in my notes, slides, or book on how to use Math.round.
You don't need Math.round() to get a resultant decimal value. If you divide an int by an int, you will get an int. if you want a decimal, then cast double to one of the input values. Then you will get a double as a result.
(double) 199 / 39
199.0 / 39
// both return
5.102564102564102
I know the answer should be 5.1 with some more decimals.
Not with integer division it shouldn't. 5 is correct.
If you want a floating-point answer, you need to provide at least one floating-point operand, e.g. 199/39.0.
You can then format that for printing with as many or few decimal places you like, with System.printf() or DecimalFormat.
You can't round the floating-point value itself to decimal places, because it doesn't have decimal places, it has binary places.
See this question for a full discussion, especially my answer there.
Your specific answer:
roundedNumber = (double)Math.round(unRoundedNumber * 10) / 10;
In general, the equation is:
roundedNumber =
(double)Math.round(unRoundedNumber * Math.pow(10, digitsToRoundTo))
/ Math.pow(10, digitsToRoundTo);
Thanks for all the help. After reading your posts and looking at it some more I ended up doing ratio=((double)199/39) and then going
ratio=(double)Math.round(ratio*10)/10. Doing that got me the 5.1 i was looking for.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Moving decimal places over in a double
Why is the following sum of numbers not equal to 0.4622? but 0.46219999999999994
Double total = new Double(0.08) + new Double(0.0491) + new Double(0.3218) +
new Double(0.0113) + new Double(0.0); // = 0.46219999999999994
I have an application that checks the users input.
The user inputs 5 decimal numbers and a total number. The application checks if the sum of all 5 numbers capped at 4 decimals behind the komma is equal to the total number.
Capping it gives me 0.4621 which is not equal to 0.4622. I can't use DecimalFormat because it rounds it up. And if i explicitly say, round down then it will fail for this situation.
Any suggestion for how I can solve this?
Try with java.math.BigDecimal. Double rounds result. You will just have to use add method, not + operator.
Avoid using float and double if exact answers are required-- Item 48 -- Effective Java Second edition
Use BigDecimal instead.
Looks like a classic case of floating point arithmetic. If you want exact calculations, use java.math.BigDecimal. Have a look at What Every Computer Scientist Should Know About Floating-Point Arithmetic
When you use floating point arithmetic you must also use appropriate rounding.
BTW: Don't use an object when a primitive will do.
double total = 0.08 + 0.0491 + 0.3218 + 0.0113 + 0.0;
System.out.printf("%.4f%n", total);
double rounded = Math.round(total * 1e4) / 1e4;
if (rounded == 0.4622)
System.out.println("rounded matched");
prints
0.4622
rounded matched
as expected.
Double and float in Java are internally represented as binary fractions and can therefore be not precise in representing decimal fractions (IEEE standard 754). If your decimal number calculations require precision, use Java.math.BigDecimal.
Floating point representation is a close approximation so you will have these little rounding errors when you use float and double. If you try to convert 0.08 to binary for instance you will realize that you cannot actually do it exactly. You need to consider this whenever you use double and float in calculations.
0.0810 = 0.00010100011110101110...2
a repeating pattern. So no matter how many bits you use this will have a rounding error.
That is yet another rounding issue. You should never compare doubles and expect them to be exactly equal. Instead define a small epsylon and expect the result to be within epsylon of the expected answer.
Any floating point value is inexact. The solution is to use DecimalFormat when you have to display the values. And no, it doesn't round up but to the nearest value.
From the javadoc :
DecimalFormat uses half-even rounding (see ROUND_HALF_EVEN) for
formatting.
The internal representation of floating point numbers like Double is never a exact one. This is why during calculations such errors can occur.
It is always suggested to format such a result to a specific number of digits past the comma, so you result would be correctly be display as "0.4622" with 4 to 15 or more digits.
Perhaps checking the string input directly would be more feasible for you. That is check the length of characters after the decimal place.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why does the division of two integers return 0.0 in Java?
I have some very confusing problem..
I want to calculate some stuff and after some debugging I saw that java calculates this arithmetic: 2 / 4 = 0.0 But it should be 0.5
2 & 4 are stored in integer variables
the result is stored in a double-type.
Did I miss something clearly?
It is because of integer division (Integer division rounds toward 0). Cast one of the operand to double type.
Example:
double temp = (double)2/4
will give you correct results.
Use
myDouble = (double) integerWhoseValueIs2 / integerWhoseValueIs4
The fact you store it in a double doesn't change the fact that the division of two integers makes an integer. When you store it, it's too late.
From the Java Language Specification :
Integer division rounds toward 0. That is, the quotient produced for
operands n and d that are integers after binary numeric promotion
(§5.6.2) is an integer value q whose magnitude is as large as possible
while satisfying |d · q| ≤ |n|.
If you do not write a cast to double, the result is always an int.
double a = (double) 2/4;