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!
Related
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);
}
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
I have two angles given to me; a starting one and an ending one.
I'm also in a loop with a specified numbers of loops.
I'm trying to split an angle up so at each loop iteration I create something at that angle.
Using 3 particles as an example
Here is the code (within in the loop, degrees are 90 to 180)
for (int i = 0; i < numberOfParticles(3); i++)
{
float percentage = 1f / numberOfParticles;
percentage *= index;
float angle = startingAngle + ((endingAngle - startingAngle) * percentage);
}
My problem is this produces : (instead of 90 (0), 135 (0.5), 180 (1))
Log: 90.0 | percentage: 0.0
Log: 120.0 | percentage: 0.33333334
Log: 149.99998 | percentage: 0.6666667
How would I get this to work with any number (including 7?)
You've got an off-by-one error. If you have 3 particles, you're going to start at 0% and then add 50% 2 times, not 3.
float percentage = 1f / (numberOfParticles - 1);
Make sure you also handle the edge case where numberOfParticles is 1. You don't want to divide by zero.
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.
This is what I did but no matter what I keep getting infinity:
public double calcr(){
double cot = 1 / Math.tan(0);
return .5 * sideLength * cot * (Math.PI / numSides);
}
Main:
RegularPolygon poly = new RegularPolygon(4, 10);
System.out.println(poly.calcr());
Output:
Inifinity
What am I doing wrong?
The problem is that you do
double cot = 1 / Math.tan(0);
which will make cot be Infinity.
You'd want:
double cot = 1 / Math.tan(Math.PI / numSides);
return .5 * sideLength * cot;
Or, in a single line:
return .5 * sideLength / Math.tan(Math.PI / numSides);
tan(0) is 0, so this line
double cot = 1 / Math.tan(0);
sets cot to Infinity. The computation below it will then also evaluate to Infinity, as you saw.
Since it looks like you're trying to evaluate cot(pi/n), you'd need 1 / Math.tan(Math.PI / n) instead of using cot * (Math.PI / numSides) with an incorrect value for cot.