Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

round to nearest nice number

Tags:

java

rounding

I'm writing an application which requires rounding labels to the nearest 'nice' number. I'll put some code below to demonstrate this, but my issue is that I was using a series of else ifs to find this number but I cannot be sure of the upper limit so this isn't really a good strategy. Are there any known algorithms or resources which could help me?

    if (diff <= 1) {
        roundAmount = 0.2;
    } else if (diff <= 5) {
        roundAmount = 1;
    } else if (diff <= 10) {
        roundAmount = 2;
    } else if (diff <= 25) {
        roundAmount = 5;
    } else if (diff <= 50) {
        roundAmount = 10;
    } else if (diff <= 100) {
        roundAmount = 20;
    } else if (diff <= 250) {
        roundAmount = 50;
    } else if (diff <= 500) {
        roundAmount = 100;
    } else if (diff <= 1000){
        roundAmount = 200;
    } etc...
like image 418
user650309 Avatar asked Oct 11 '11 11:10

user650309


People also ask

How do you round a number to the nearest 5 in C#?

int test = 5 * (value / 5); for the next value (step 5) above, just add 5. Be careful here. If value is int, it always rounds down.

How do you round of to the nearest?

If the number you are rounding is followed by 5, 6, 7, 8, or 9, round the number up. Example: 38 rounded to the nearest ten is 40. If the number you are rounding is followed by 0, 1, 2, 3, or 4, round the number down. Example: 33 rounded to the nearest ten is 30.

What is the rounding of a number?

Rounding is a process to estimate a particular number in a context. To round a number look at the next digit in the right place, if the digit is less than 5, round down and if the digit is 5 or more than 5, round up. Rounding decimals refer to the rounding of decimal numbers to a certain degree of accuracy.

How do you round to a specific number in C#?

In C#, Math. Round() is a Math class method which is used to round a value to the nearest integer or to the particular number of fractional digits. This method has another overload with which, you can specify the number of digits beyond the decimal point in the returned value.


2 Answers

You can use Math.log10 to normalize all values before doing your "nice number" search, something like this:

[Edit] I just realized you are using Java instead of C#, so I modified the code a bit. I don't have a compiler around to test it, but you should get the general idea anyway:

static double getNicerNumber(double val)
{
    // get the first larger power of 10
    var nice = Math.pow(10, Math.ceiling(Math.log10(val)));

    // scale the power to a "nice enough" value
    if (val < 0.25 * nice)
        nice = 0.25 * nice;
    else if (val < 0.5 * nice)
        nice = 0.5 * nice;

    return nice;
}

// test program:
static void main(string[] args)
{
    double[] values = 
    {
        0.1, 0.2, 0.7,
        1, 2, 9,
        25, 58, 99,
        158, 267, 832
    };

    for (var val : values)
        System.out.printf("$%.2f --> $%.2f%n", val, getNicerNumber(val));
}

This will print something like:

0,1 --> 0,1
0,2 --> 0,25
0,7 --> 1
1 --> 1
2 --> 2,5
9 --> 10
25 --> 50
58 --> 100
99 --> 100
158 --> 250
267 --> 500
832 --> 1000
like image 178
Groo Avatar answered Oct 31 '22 07:10

Groo


I prefer the following over Groo's approach, as it rounds 267 to 275 instead of 500. It basically rounds to the first digit, and then the nearest quarter fraction of that power of 10.

static double round_pretty(double val) {
    var fraction = 1;
    var log = Math.floor(Math.log10(val));

    // This keeps from adding digits after the decimal
    if(log > 1) {
        fraction = 4;
    }

    return Math.round(val * fraction * Math.pow(10, -log)) 
        / fraction / Math.pow(10, -log);
}

The output is as follows:

0.01 -> 0.01
0.025 -> 0.03    (Groo's does 0.025)
0.1 -> 0.1
0.2 -> 0.2       (Groo's does 0.25)
0.49 -> 0.5
0.5 -> 0.5       (Groo's does 1)
0.51 -> 0.5      (Groo's does 1)
0.7 -> 0.7       (Groo's does 1)
1 -> 1
2 -> 2           (Groo's does 2.5)
9 -> 9
23.07 -> 20
25 -> 30
49 -> 50
50 -> 50         (Groo's does 100 here)
58 -> 60
94 -> 90
95 -> 100
99 -> 100
100 -> 100
109 -> 100       (Groo's does 250 here)
158 -> 150
249 -> 250
267 -> 275
832 -> 825
1234567 -> 1250000
1499999 -> 1500000
1625000 -> 1750000
like image 33
LeBleu Avatar answered Oct 31 '22 07:10

LeBleu