问题
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
回答1:
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
rcan be thought as the value of a fractional unit.- When
r = 0.25, the fractional unit is a quarter.
- When
- The value
x/rrepresents the number of fractional units that make upx.- When
x = 0.75,r = 0.25,x/r == 3, becausexcontains three fractional unit, which is the quarter.x/rrepresents the number of quarters.
- When
Math.round(x)roundsxto the nearest integral value. Similarly,Math.round(x/r)roundsx/rto the nearest integral multiple of that fraction.- For
x = 0.7, r = 0.25, we havex/r = 2.8, representing 2.8 quarters.Math.round(x/r)therefore rounds the value to the nearest quarter, 3 quarters.
- For
Math.round(x/r)*rtherefore roundsxto the nearest fractional intervalr. The multiplier is needed becauseris 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 byr=0.25to get the rounded value ofx.
- For
回答2:
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);
}
来源:https://stackoverflow.com/questions/50580602/round-double-to-number-in-interval-defining-by-step