Rounding off in java - java

I have a list that contains many decimal values.
If i get a value of .032 i have to
round it off to 3.2%
If i get a value
of 32.33 i have to round it off to
32%
If i get a value of 32.66 i have to round it off to 33%
if decimal digit is 5,6,7,8 or 9
round up to the next
how should i go bt dng this?

Use Math.round(). This correctly rounds a number upwards if the fractional part is 0.5 or greater.

If I understood you question correctly:
For the first point, you can use DecimalFormat class, see API
I'm not sure why you'd want to "round" 32.33 -> 32% as this is not rounding. If you are parsing user input data which could be given in this way, you can divide by 100 (giving 0.3233) and use DecimalFormat.
For the others you can use Math.round() as adviced below/above

Math.round() and convert it to percent form.
I doubt about .032 case. rest are looking good.

Use MathUtils (Apache Commons Math)
MathUtils.round(double, scale, roundingMethod);
scale - The number of digits to the right of the decimal point. (+/-)
roundingMethod : BigDecimal.ROUND_DOWN, #.ROUND_CEILING, #.ROUND_HALF_UP, ...

Related

Java - unexpected result when rounding a double/float to 2 decimals

I encounter a problem when round a double to 2 decimals. I know this questions have been asked in many places. But my question is slightly different and I cannot find it in other places.
So far as I know, there are 2 ways to do this.
Math.round(double*100.0)/100.0
DecimalFormat(“###.##”)
I am trying to use the first way: a custom way to round double.
When the second decimal is 0, the result will only print the first decimal and ignore the second one.
For example,
Math.round(1.23333*100.0)/100.0 The result is 1.23. This works good.
Math.round(3.90*100.0)/100.0. The result is 3.9. Problem occurs. I want to show 3.90 instead of 3.9
Math.round(3*100.0)/100.0. The result is 4.0. I want 4.00 instead of 4.0
So, my question is that how I can have a double value with 2 decimals no matter if the last decimal is 0 or not. I know I can use the second way- DecimalFormat(“###.##”) to achieve what I want! But is it possible to do it by using the first way?
Edit: Thanks for the answers. It looks like it is NOT possible to use the round() method to achieve it. However, some people suggest to use the combination of 2 ways to achieve it. But I think using only DecimalFormat(“###.##”) can get what I want. Can anyone confirm it?
I would suggest using String.format("%1$.2f",x). It rounds the value to the specified precision (2 digits in our example) and leaves the trailing zeros on the right.
System.out.println(String.format("%1$.2f",3.121)) gives 3.12
System.out.println(String.format("%1$.2f",3.129)) gives 3.13
System.out.println(String.format("%1$.2f",3.12)) gives 3.12
System.out.println(String.format("%1$.2f",3.10)) gives 3.10
Have you tried the following?
DecimalFormat(“###.00”)
If not mistaken, trailing zeros are left blank when using the #-sign.
I believe you need to use a combination of both to achieve your needs.
The rounding to obtain a number with two decimals, and the DecimalFormat to display it with two decimals.
You should be formatting your result with DecimalFormat
DecimalFormat format = new DecimalFormat("0.00");
System.out.println(Math.round(3.90*100.0)/100.0); // 3.9
System.out.println(format.format(Math.round(3.90*100.0)/100.0)); // after using format 3.90
System.out.println(format.format(Math.round(3*100.0)/100.0));
And the output is
3.9
3.90
3.00

Java sum of all double does not return expected result [duplicate]

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.

Unify 10^x power in a sequence of number

I have a sequence of numbers like this:
1.687155E21
3.981457E19
0.5532155E21
3.018843E21
2.0532155E21
4.5532155E21
3.1637913E19
My problem is how to convert the two numbers which ends with 10^19 to be like the others (10^21). Because after this unification i need to trunc the number to print only something like 3.5.
In C/C++ i know how to work with precision, but in Java I haven't got any idea.
Divide all your number by / 1e19, round to as many decimal digits you want:
168.7155
3.981457
55.32155
301.8843
205.32155
455.32155
3.1637913
Use the Formatter Class to bring them into the desired scientific notation (java.util.Formatter)
I'd suggest something similar as Tomasz Nurkiewicz did, but instead of dividing by 1E19 divide by 1E21, convert them to strings with the required precision using Formatter (see the comment of count0) but not as scientific format, but as a general one. In the end just add E21 to those strings. In the end you should get (I hope, I got the idea correctly)
1.687155E21
0.03981457E21
0.5532155E21
3.018843E21
2.0532155E21
4.5532155E21
0.031637913E21
Can't you just multiply the E19 numbers by 10 ^ 2 = 100?
After they have been normalized to E21, you should be able to divide all of them by 10^21 (if they're floats), and they will all be in the range of 0-9.999...

Weird floor rounding [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Moving decimal places over in a double
I am having this weird problem in Java, I have following code:
double velocity = -0.07;
System.out.println("raw value " + velocity*200 );
System.out.println("floored value " + Math.floor(velocity*200) );
I have following output:
raw value -14.000000000000002
floored value -15.0
Those traling 0002 screw everything up, and BTW there should not be that traling 2, I think it should be all zeroes after decimal point, can I get rid of that 2?
Update: Thanks for help, Guys do you know any way to make floor rounding on BigDecimal object without calling doubleValue method?
Because floor(-14.000000000000002) is indeed -15!
You see, floor is defined as the maximal whole number less or equal to the argument. As -14.000000000000002 is not a whole number, the closest whole number downwards is -15.
Well, now let's clear why -0.07 * 200 is not exactly -14. This is because the inner representation of floating-point numbers is in base 2, so the fractions where the denominator is not a power of 2 cannot be represented with 100% precision. (The same way as you cannot represent 1/3 as the decimal fraction with finite amount of decimal places.) So, the value of velocity is not exactly -0.07. (When the compiler sees the constant -0.07, it silently replaces it with a binary fraction which is quite close to -0.07, but not actually equal to.) This is why velocity * 200 is not exactly -14.
From The Floating-Point Guide:
Why don’t my numbers, like 0.1 + 0.2 add up to a nice round 0.3, and instead I get a weird result like 0.30000000000000004?
Because 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.
If you need numbers that exactly add up to specific expected values, you cannot use double. Read the linked-to site for details.
Use BigDecimal... The problem above is a well-known rounding problem with the representation schemes used on a computer with finite-memory. The problem is that the answer is repetitive in the binary (that is, base 2) system (i.e. like 1/3 = 0.33333333... with decimal) and cannot be presented correctly. A good example of this is 1/10 = 0.1 which is 0.000110011001100110011001100110011... in binary. After some point the 1s and 0s have to end, causing the perceived error.
Hope you're not working on life-critical stuff... for example http://www.ima.umn.edu/~arnold/disasters/patriot.html. 28 people lost their lives due to a rounding error.
Java doubles follow the IEEE 754 floating-point arithmetic, which can't represent every single real number with infinite accuracy. This round up is normal. You can't get rid of it in the internal representation. You can of course use String.format to print the result.

Problems with double

I'm storing a number as a double. It works well with small numbers but if the double is 1000000 and I try to add 10 to it, it doesn't work but I can add 100 to it. If the double is 100000 and I try to add 1 to it, it doesn't work but I can add 10 to it.
Is this a problem with using a double? What format should I be using for up to a 9 digit number?
Edit: I'm doing calculations on the number and putting it in a 0.00 decimal format. It works on small numbers but not on big. It might have something to do with the other calculations. Just seeing if maybe double was the problem.
I run into problems when I take 1000001 / 100 and put in 0.00 decimal format. But 1000100 / 100 put into a 0.00 dec format works.
Not sure what you mean by "it doesn't work", considering that it should:
System.out.println(1000000d + 10d); // 1000010.0
Cases where it wouldn't work are where there is a value that is more than about 15 digits from the most significant digit of the largest double involved:
System.out.println(Math.pow(10, 18) + 10d - Math.pow(10, 18)); // 0.0
System.out.println(Math.pow(10, 17) + 10d - Math.pow(10, 17)); // 16.0
System.out.println(Math.pow(10, 16) + 10d - Math.pow(10, 16)); // 10.0
An int is absolutely large enough to store a 9-digit number, since the maximum value stored by a (signed) integer is 2^31 - 1 = 2,147,483,647 which has 10 digits.
If you need a larger range, use a long.
Java Tutorial: Primitive Data Types
Yes, this is how floating point works in general. (Although, as others pointed out, this should be well within the actual capabilities of double.) It loses more and more precision as the number is getting bigger. And even with small numbers, it isn't guaranteed to be precise. For small integers it is, as a general rule, but in practice, relying on the precision of floating point is a bad idea.
For integers, long should be good enough, 263-1 is the biggest number you can store in it.
Otherwise BigDecimal is the answer. Not very convenient, but it is precise.
Judging by the update to your question, you want to store prices or something similar. In that case, you can either use a library dedicated to currency arithmetic (as there are often weird rules of rounding involved for example), or store pennies/cents in a long.
A double is actually able to hold that result. The most likely thing is probably that you're inspecting/printing out the number in such a way that appears like the number isn't different (could you post your test code?).
As a general rule of thumb, doubles give you ~16 digits of precision, and floats give you ~8 digits of precision.
What kind of 9-digit number do you need to keep? A double should have enough precision track 9 significant digits as would an int, but you need to know which type of number you need before you choose a type. If you need real values (i.e., they have digits to the right of the decimal), then choose double. If they are integers, choose int.
I don't think your exact problem is very clear. Are you using integer arithmetic? In which case you should expect an integer division to round down the answer.
int i = 1000001 / 100;
System.out.println(i);
double d = (double) 1000001 / 100;
System.out.println(d);
prints as expected
10000
10000.01
However, since you have't given a clear example of what does work and what you expect to happen, we are just guessing what your problem might be.
Nevertheless, there is something wrong. It should be possible to (ab)use a double (which is in 64bit IEEE format in Java) as an 48-bit-or so integer. 48 bt should be enough to store 9 decimal digits.

Categories