Round according to nearest decimal value - java - java

I have used this one
Math.round(input * 100.0) / 100.0;
but it didn't work with my requirement. I want to round into two decimal points according to nearest decimal value.
firstly I want to check fourth decimal value
if it is 5 or above I want to add 1 into 3rd decimal value
then want to check 3rd one
if it is 5 or above I want to add 1 into 2nd one
ex: if I have 22.3246
refer above example number. 4th decimal no is 6.
we can add 1 into 3rd decimal value.
result : 22.325
now 3rd decimal no is 5. we can add 1 into 2nd decimal value
result : 22.33
I want to get result 22.33

If you want to respect the 4th decimal digit, you can do it in this way:
double val = Math.round(22.3246 * 1000.0) / 1000.0;
double result = Math.round(val * 100.0) / 100.0;
System.out.println(result); // print: 22.33

You can use BigDecimal class to accomplish this task, in combination with a scale and RoundingMode.HALF_UP.
Sample code:
System.out.println(new BigDecimal("22.3246").divide(BigDecimal.ONE,3,RoundingMode.HALF_UP)
.divide(BigDecimal.ONE,2,RoundingMode.HALF_UP));
Output:
22.33

According to your requirement, the greatest number to be rounded down to 22.32 is 22.3244444444.... From 22.32444...4445 on, iteratively rounding digit per digit will lead to 22.33.
So, you can add a bias of 0.005 - 0.0044444444 (standard rounding threshold minus your threshold), being 5/9000 and then round to the next 1/100 the standard way:
double BIAS = 5.0 / 9000.0;
double result = Math.round((input + BIAS) * 100.0) / 100.0;

Related

How to round to 2.5 in Java?

So I am making a fitness app for android and now I am asking the user to input a number e.g. 72.5
I would take this number and take percentages of it and apply functions to this etc.
I need to make sure that the percentage I take of that number is rounded to 2.5. This is because in a UK gym you only have the following plates: 1.25x2=2.5 2.5x2=5 5+2.5=7.5 , 10, 15, 20, 25
What I mean is that it would be numbers like these: 40, 42.5, 45, 47.5, 50
How can I round a Number N to the nearest 2.5? I understand that math.Round() rounds to nearest whole but what about to a custom number like this?
Do it as follows:
public class Main {
public static void main(String args[]) {
// Tests
System.out.println(roundToNearest2Point5(12));
System.out.println(roundToNearest2Point5(14));
System.out.println(roundToNearest2Point5(13));
System.out.println(roundToNearest2Point5(11));
}
static double roundToNearest2Point5(double n) {
return Math.round(n * 0.4) / 0.4;
}
}
Output:
12.5
15.0
12.5
10.0
Explanation:
It will be easier to understand with the following example:
double n = 20 / 3.0;
System.out.println(n);
System.out.println(Math.round(n));
System.out.println(Math.round(n * 100.0));
System.out.println(Math.round(n * 100.0) / 100.0);
Output:
6.666666666666667
7
667
6.67
As you can see here, rounding 20 / 3.0 returns 7 (which is the floor value after adding 0.5 to 20 / 3.0. Check this to understand the implementation). However, if you wanted to round it up to the nearest 1/100th place (i.e. up to 2 decimal places), an easier way (but not so precise. Check this for more precise way) would be to round n * 100.0 (which would make it 667) and then divide it by 100.0 which would give 6.67 (i.e. up to 2 decimal places). Note that 1 / (1 / 100.0) = 100.0
Similarly, to round the number to the nearest 2.5th place, you will need to do the same thing with 1 / 2.5 = 0.4 i.e. Math.round(n * 0.4) / 0.4.
To round a number to the nearest 100th place, you will need to do the same thing with 1 / 100 = 0.01 i.e. Math.round(n * 0.1) / 0.1.
To round a number to the nearest 0.5th place, you will need to do the same thing with 1 / 0.5 = 2.0 i.e. Math.round(n * 2.0) / 2.0.
I hope, it is clear.
Late reply but you can also do 2.5*(Math.round(number/2.5))
Same way if you wanted to round in lbs to the nearest 5th its 5*(Math.round(number/5))

print number with 2 digits but round with 6 digits of precision

For getting a String with exactly 2 digits after the "." I can do something like:
DecimalFormat df = (DecimalFormat)DecimalFormat.getInstance(Locale.US);
df.applyPattern("0.00");
df.setRoundingMode(RoundingMode.HALF_UP);
String output = df.format(value);
When I have a number such as 828.054999999702d, it will format it to 828.05 what is so far correct, since the next digit says "4" and it will round that down to nothing.
But what if I need to preserve more digits precision, just don't want to show it?
What I quickly created is this working code:
double prettyValue = value;
prettyValue = Math.round(prettyValue * 1000000d) / 1000000d;
prettyValue = Math.round(prettyValue * 100000d) / 100000d;
prettyValue = Math.round(prettyValue * 10000d) / 10000d;
prettyValue = Math.round(prettyValue * 1000d) / 1000d;
prettyValue = Math.round(prettyValue * 100d) / 100d;
DecimalFormat df = (DecimalFormat)DecimalFormat.getInstance(Locale.US);
df.applyPattern("0.00");
df.setRoundingMode(RoundingMode.HALF_UP);
String output = df.format(prettyValue);
This will round the 6th, 5th, 4th, 3th and then the second place, NumberFormat will not have to do anything but just print the 2 remaining digits, after that there will be zeroes.
But I think there should be already an out-of-the-box rounding that I just don't see. Trying to do the same with BigDecimals leads to exactly the same issue for me.
The result I want is to get 828.054999999702 rounded to 828.06.
I'm not sure I fully understand your question so let me recap:
You have some double value with potentially more than 6 significant fraction digits.
You want to round that value to 6 fraction digits and use the HALF_UP mode.
You want to display only the first 2 fraction digits (I don't understand why but I won't question it).
In that case I'd suggest you first use BigDecimal for the rounding since otherwise you could get precision errors:
double value = 1.23456789;
BigDecimal rounded = BigDecimal.valueOf( value ).setScale(6, RoundingMode.HALF_UP);
That should result in the value 1.234568.
Then use NumberFormat like you did but always round down:
DecimalFormat df = (DecimalFormat)DecimalFormat.getInstance(Locale.US);
df.applyPattern("#.##");
df.setRoundingMode(RoundingMode.DOWN);
String output = df.format( rounded );
That should result in 1.23.
With your input value of 4.23499999999235 you'd then get 4.235000 (rounded to 6 digits) and 4.23.
Edit: I'm not aware of any rounding mode that rounds 4.23499999999235 to 4.24 but you should be able to achieve it by chaining multiple setScale() calls:
BigDecimal rounded = BigDecimal.valueOf( value );
for( int digit = 6; digit >= 2; digit--) {
rounded = rounded .setScale( digit, RoundingMode.HALF_UP );
}
That should apply rounding to fraction digit 6, then 5 etc. and finally round to 4.24. I'm still not sure that's the right way to round but you know your requirements better than me :)
Considering you are outputting this to a string, why not use
String output = String.format(java.util.Locale.US,"%.2f", doubleValue);
instead of all of the DecimalFormat stuff? This will leave doubleValue as the original value, keeping the precision.

Double value with two decimals and a round on last number

I have some double values like
3.1795926
25.549000
11.11004
My goal is to get
3.20
25.55
11.10
If I use the function Mathematical.FFIX(3.1795926,2) I can get it to two decimals like I want, but it don't round as I want to. It gives me 3.18.
How can i do this?
You can do the following:
double d = 25.549000;
d = 0.05*(Math.round(d/0.05));
You can try something like following
double value = 3.1795926;
(double)Math.round(value * 100) / 100
That is for 2 digits precision.

Floating point precision with Math.Ceil (Java)

I'm implementing a business rule to calculate a percentage increase on a stock level:
Stock level | Percentage Increase | Expected output
100 | 93 | 193
As decimal stock levels are not well defined the rule is to round up the output:
public int calculateStockLevel(int rawStockLevel, double percentageIncrease) {
return Math.ceil(rawStockLevel * (1 + (percentageIncrease / 100));
}
Actual output for the situation above: 194 (The test fails)
This looks like a floating point precision error, whats an elegant & readable way to get this test to pass?
You should use BigDecimal to specify what precision you want, but for your case you could do something simpler: just divide by 100 at the end.
public int calculateStockLevel(int rawStockLevel, double percentageIncrease) {
return Math.ceil(rawStockLevel * (100 + percentageIncrease) / 100);
}
Binary floating-point types can't represent exactly every value in decimal. So percentageIncrease / 100 will get the closest representation in binary. In your case the exact value of 0.93 in double precision is 0.930000000000000048849813083507, which is slightly more than the true decimal value. Therefore after ceil it'll be rounded up to 0.94
If you want exact decimal output you must use decimal arithmetic, like BigDecimal. But in your case you can just do it in plain integer, utilizing the fact that the fractional part of the result must be larger than 0 if remainder of the division is non-zero.
int temp = rawStockLevel * (100 + percentageIncrease);
int result = temp/100;
if (temp % 100 != 0)
result++; // round up if not divisible by 100
return result;

unexpected results with decimal arithmetic expression

I have some business logic with arithmetic expression and their results are as follows
(10.0 * 20.58)/1.0=205.7999..98
(6.0 * 37.9)/1.0=227.3999..98
(5.0 * 50.0)/1.0=250.0
(10.0 * 37.9)/1.0=379.0
But expected results are
(10.0 * 20.58)/1.0=205.8
(6.0 * 37.9)/1.0=227.4
(5.0 * 50.0)/1.0=250.0
(10.0 * 37.9)/1.0=379.0
I am not clear why we are getting that .999..98 fraction part? Due to that my equals comparison is failing and so business logic. For few cases we are using
amt = (double)Math.round(orderAmt*100000)/100000;
But that is not possible to do the same in each and every place where we have double arithmetic expression.
I want to know why we get such results randomly and is there any possibility to round the results to 5 decimal places instead of rounding every where?
With radix 10 there are some fractions who can't be expressed exactly with a finite number of digits, like for example 1/3 = 0.33333333....
It's the same with radix 2, except that the dividers that produce this kind of results are not the one we are accustomed to, and for example, for 20.58, which is 2058 / 100, it is the case.
Internally, doubles and floats are stored with bits (an not digit), so the exact value of the double or float just can't be stored in the computer's memory. Each time you perform an operation with this value, you get a small shift, because of the approximation, which becomes visible when converting back to decimal format for printing.
It's something you have to pay attention while perfoming computations where precision is important.
So you have two solutions:
Store all your numbers in decimal type and perform all your calculation with it. This will achieve accuracy but for the price of performance.
You can also keep all the calculation with double or float, and format with a fixed number of digits only for printing results.
You could use BigDecimal for roundoff
BigDecimal bd = new BigDecimal((10.0 * 20.58)/1.0) ;
bd = bd.setScale(4, RoundingMode.UP);
use with a static method
public static double round(double value, int digits) {
BigDecimal bd = new BigDecimal(value);
return bd.setScale(digits, RoundingMode.UP).doubleValue();
}
RoundingMode has :
RoundingMode.UP;
RoundingMode.DOWN;
RoundingMode.HALF_DOWN;
RoundingMode.HALF_EVEN;
The basic problem is that
System.out.println(10.0 * 20.58);
prints
205.79999999999998
has a small rounding error due to a representation error in 20.58
You either need to
round the result before comparing.
use a comparision which allows for some error
use BigDecimal (which is over kill in most cases)
use cents instead of dollars i.e. use int or long with fixed precision.
In the last case, the same operation would read
System.out.println(10 * 2058);
prints
20580
where this is 100x the value you need as its fixed precision e.g. cents instead of dollars.
You may want to use double with rounding as below:
double roundingPlaces = 10.0;//use 10.0 for single decimal digit rounding
double a1 = 10.0;
double b1 = 20.58;
double c1 = 1.0;
System.out.println(Math.round((a1*b1*roundingPlaces)/c1)/roundingPlaces);
This prints 205.8.
float fa1 = (float) 10.0;
float fb1 = (float)20.58;
float fc1 = (float)1.0;
System.out.println(fa1*fb1/fc1);
This also prints 205.8
Use float instead of double
http://ideone.com/L9vwR8
System.out.println((float)((10.0f * 20.58f)/1.0f));
output
205.8

Categories

Resources