Android - How to customize rounding value? - java

Hi i really bad at rounding. i am trying to round up a value to the rounding of my country currency.
The rounding example will be :
1.01 > 1.00
1.02 > 1.00
1.03 > 1.05
1.04 > 1.05
1.06 > 1.05
1.07 > 1.05
1.08 > 1.10
1.09 > 1.10
How can i do this kind of rounding? Thanks a lot .

Looks like you're rounding by 0.05 = 1/20th. So the following works:
public static double roundCurrency( double value ) {
return Math.round(value * 20.0 ) / 20.0;
}

This seems to give you the correct mappings - you may need to tweak it when you decide exactly where the cutoffs are.
public void test() {
double [] tests = new double[] {1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9};
for ( double d : tests) {
System.out.println(" "+d + " -> "+round(d, .05, 0.5));
}
}
double round(double d, double fraction, double bias) {
return Math.floor(d / fraction + bias) * fraction;
}
This prints:
1.01 -> 1.0
1.02 -> 1.0
1.03 -> 1.05
1.04 -> 1.05
1.05 -> 1.05
1.06 -> 1.05
1.07 -> 1.05
1.08 -> 1.1
1.09 -> 1.1

double roundedvalue= Math.round( YourValue* 100.0 ) / 100.0;

double roundedvalue= Math.round( YourValue* 2.0 ) / 2.0;

Math.round lets you round a number to the nearest integer. It looks like you're trying to round to the nearest multiple of 0.5. The general way to solve problems like that is
roundedValue = Math.round (X / M) * M;
to round to the nearest multiple of M. So in your case that would be
roundedValue = Math.round (X / 0.5) * 0.5;
which is the same as
roundedValue = Math.round (X * 2.0) / 2.0;
Similarly, if you wanted to round something to the nearest multiple of, say, 0.01, one of these would work:
roundedValue = Math.round (X / 0.01) * 0.01;
roundedValue = Math.round (X * 100.0) / 100.0;
EDIT: It looks like you've changed your question, so what I said earlier about rounding to the nearest multiple of 0.5 isn't correct any more, and now you're rounding to the nearest multiple of 0.05. Anyway, the general method I've discussed still works.

Take a look at the http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html documentation on the Math Class. It lets you perform operations such as Math.round(double x) and
Math.ceil(double x) and Math.floor(double x) . You can use these in combination with an if else statement such as
double value = 1.6;
String valueToString = Double.toString(value);
String [] numbers = valueToString.split(".");
String decimalNums = numbers[1];
int decimal = Integer.parseInt(decimalNums);
if(decimal > 0 && decimal < 5){
decimal = Math.floor(decimal);
}else if(decimal >= 5 && decimal < 8){
decimal = 5;
}else{
decimal = Math.ceil(decimal);
}
This will only work for values that have one decimal place. But its a start. Hope it helps a little.

Related

Round double to number in interval, defining by step

I have some abstract double interval, defining by step f.e.:
0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 - where interval == 0.1
0.0, 0.25, 0.5, 0.75, 1.0 - where interval == 0.25
0.0, 0.5, 1.0 - where interval == 0.5
Does Java have some instrument to "round" some double to closest number, according to interval? f.e:
0.511111 - to 0.5 in first case
0.599999 - to 0.6 in first case
0.511111 - to 0.5 in second case
0.599999 - to 0.5 in second case
0.711111 - to 0.75 in second case
0.744444 - to 0.5 in third case
0.755555 - to 1.0 in third case
0.92222 - to 1.0 in third case
Java has instruments which can round numbers to n decimal places, see How to round a number to n decimal places in Java. For rounding to any interval you specified, you may have to manually use Math.round.
Formula:
Given an interval r and a double value x to round, a simple formula is:
x_rounded = Math.round(x/r)*r;
Examples:
double x = 0.59999;
double r = 0.25; // Quarters
x = Math.round(x/r)*r;
System.out.println(x); // Result is 0.5
double x = 0.59999;
double r = 0.1; // Tenths
x = Math.round(x/r)*r;
System.out.println(x); // Result is approximately 0.6
double x = 0.31421;
double r = 0.125; // Eighths
x = Math.round(x/r)*r;
System.out.println(x); // Result is exactly 0.375
Proof:
The interval r can be thought as the value of a fractional unit.
When r = 0.25, the fractional unit is a quarter.
The value x/r represents the number of fractional units that make up x.
When x = 0.75, r = 0.25, x/r == 3, because x contains three fractional unit, which is the quarter. x/r represents the number of quarters.
Math.round(x) rounds x to the nearest integral value. Similarly, Math.round(x/r) rounds x/r to the nearest integral multiple of that fraction.
For x = 0.7, r = 0.25, we have x/r = 2.8, representing 2.8 quarters. Math.round(x/r) therefore rounds the value to the nearest quarter, 3 quarters.
Math.round(x/r)*r therefore rounds x to the nearest fractional interval r. The multiplier is needed because r is the value of each fractional unit.
For x = 0.7, r = 0.25, Math.round(x/r) represents 3 quarters. It has to be multiplied by r=0.25 to get the rounded value of x.
Use BigDecimal and setScale() to round.
However it will not work with the 0.25 precision, but you might do a workaround, something like this:
public BigDecimal round( BigDecimal value, BigDecimal precision )
{
return value.divide(precision, BigDecimal.ROUND_HALF_UP)
.round(BigDecimal.ROUND_HALF_UP)
.multiply(precision, BigDecimal.ROUND_HALF_UP);
}

Is there a replacement for this double math

Is there a Java operator that would create a value equal to count but in fewer lines?
double theta = //Some value;
int count = 0;
while (theta > 0) {
theta -= pi * (1.0 / 8.0);
count += 1;
}
You've just implemented division by repeated subtraction.
So, if you had actual real numbers in Java, you could do ...
int result = (int) (theta / (Math.PI / 8)) + 1;
... to get the same result. However due to repeated rounding errors in your code, that has many more steps than a simple division, the answers will diverge a bit. The results will be the same for thetas up to around 55 million.
The rounding errors are there because float and double are not accurate representations of real numbers.
See also: Is floating point math broken?
Assuming theta > 0, something like this should work:
int count = (int)Math.ceil (theta/(Math.PI * (1.0 / 8.0)));
or
int count = (int)Math.ceil (theta*8/Math.PI);
How about this: Math.ceil( theta/(pi * (1.0 / 8.0)))?

Floating-point precision when dealing with trigonometric functions

I have a Java class that deals with a lot of trigonometric functions using java.lang.Math. The following code determines the average direction of 0 degrees and 180 degrees. The result should be NaN, since 0 degrees and 180 degrees are in opposite directions, canceling each other out. However, when I do:
double[] angles = {0, 180};
double sines = 0;
double cosines = 0;
double avg;
for (int i = 0; i < angles.length; i++) {
double rad = Math.toRadians(angles[i]);
sines += Math.sin(rad);
cosines += Math.cos(rad);
}
double sin = sines / angles.length;
double cos = cosines / angles.length;
System.out.println("Avg sin: " + sin + "\nAvg cos: " + cos); // sin != 0 but it should
double avgRad = Math.atan2(sin, cos);
avg = Math.toDegrees(avgRad);
System.out.println("Average: " + avg);
avg equals 90.0 instead of NaN. This is because the average sine of 180 degrees and 0 degrees results in a very small but positive number (due to the way floating-point precision works). If you run the above code you will see what I mean. How can I avoid this lack of precision? I know that I could round the average sines and cosines as well as the final result, but that seems a little inelegant to me.
I take it granted that you must have considered averaging angles directly (by using mod 360) before you went onto use sin/cos/tan. That being said, I think, you are in right direction in getting what you intended in your code (except possibly the negative sign flip in the last example).
~> java Main 0 180
Avg sin: 6.123233995736766E-17
Avg cos: 0.0
Average: 90.0
~> java Main 0 179
Avg sin: 0.00872620321864172
Avg cos: 7.615242180436521E-5
Average: 89.50000000000011
~> java Main 1 179
Avg sin: 0.017452406437283477
Avg cos: 0.0
Average: 90.0
~> java Main 1 180
Avg sin: 0.008726203218641817
Avg cos: -7.615242180436521E-5
Average: 90.49999999999991
~> java Main 1 181
Avg sin: 1.5959455978986625E-16
Avg cos: 0.0
Average: 90.0
~> java Main 1 182
Avg sin: -0.008723545132608694
Avg cos: 2.2843406864775373E-4
Average: -88.50000000000001

Very unusual rounding

Did you ever make a rounding like that:
[0.95,1) rounds to 1
[0.90,0.95) rounds to 0.95
[0.85,0.90) rounds to 0.90
[0.80,0.85) rounds to 0.85
I tried to do like this:
double rounded = Math.round(x * 20.0) / 20.0;
But it rounds a bit different, for example it rounds 0.91 to 0.90 and I rather need it to round 0.91 to 0.95
The number you're looking for can be found by
Multiplying your number by 20.
Computing the floor of your number.
Dividing your number by 20.
Adding 0.05
For example, ⌊ 0.95 * 20 ⌋ / 20 + 0.05 = ⌊ 19 ⌋ / 20 + 0.05 = 0.95 + 0.05 = 1.00.
In Java:
double result = Math.floor(x * 20.0) / 20.0 + 0.05;
Hope this helps!

Java - How to round up float (or BigDecimal ) value by 0.5?

Seems simple question but I really suck at math and few examples online I've searched seems not working for me. (the result just return the same value as input etc)
For instance.. but its in C not Java
Round to Next .05 in C
So my goal is I have %.1f format float or double or big decimal and wanting to round it up to nearest .5
example:
1.3 --> 1.5
5.5 --> 5.5
2.4 --> 2.5
3.6 --> 4.0
7.9 --> 8.0
I tried following example but didn't work :( below just output 1.3 which is original value. I wanted it to be 1.5
public class tmp {
public static void main(String[] args) {
double foo = 1.3;
double mid = 20 * foo;
System.out.println("mid " + mid);
double out = Math.ceil(mid);
System.out.println("out after ceil " + out);
System.out.printf("%.1f\n", out/20.0);
}
}
Here's a simple method:
public static float roundToHalf(float x) {
return (float) (Math.ceil(x * 2) / 2);
}
This doubles the value, takes its ceiling, and cuts it back in half.
Multiplying (and later dividing) by 2, not 20, should do the trick.
double nearestPoint5 = Math.ceil(d * 2) / 2;
The below formula does not work well for number like 2.16
public static float roundToHalf(float x) {
return (float) (Math.ceil(x * 2) / 2);
}
The correct answer should be 2.0, but the above method gives 2.5
The correct code should be:
public static double round(float d)
{
return 0.5 * Math.round(d * 2);
}
See the Big Decimal Javadoc about why a String is used in the constructor
public static double round(double d, int decimalPlace){
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace,BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
}
Without using a function, you can do
double rounded = (double)(long)(x * 2 + 0.5) / 2;
Note: this will round towards infinity.
Some of the other answers round incorrectly (Math.round should be used, not Math.floor or Math.ceil), and others only work for rounding to 0.5 (which is what the question asked, yes). Here's a simple method that correctly rounds to the nearest arbitrary double, with a check to assure that it's a positive number.
public static double roundToNearest(double d, double toNearest) {
if (toNearest <= 0) {
throw new IllegalArgumentException(
"toNearest must be positive, encountered " + toNearest);
}
return Math.round(d/toNearest) * toNearest;
}

Categories