0

Is there a generic reliable way of calculating bar chart axises? Im looking for an algorithm that should round up to the next "proper" number.

In the bar chart below the y-axis is 0 - 300 with a sequence step of 75 In the image the y-axis is 0 - 300 with a sequence step of 75

Im thinking this algorithm should accept an array of numbers and:

a) determine the min/max (in this case 25 and 250)

b) determine the "proper" max (in this case 300)

If the min/max was 25/240 - the "proper" max would be 250. Anything over 250 would result in a "proper" max of 300.

I'm looking for an intelligent way of rounding up an arbitrary number.

Any ideas?

Mani
  • 1,597
  • 15
  • 19
  • 3
    Explain more precisely what you mean by "bar chart axises", "proper number" and "max axis value on the right". – nbro Oct 02 '17 at 20:42
  • 1
    It's probably best practice not to have your y-axis in multiples of 75. Typically axis ticks are in multiples of 1, 2, 2.5 or 5 times a power of 10 – c2huc2hu Oct 02 '17 at 21:18
  • Look for some implementation of Paul Heckbert's article "Nice numbers fir graph labels" – MBo Oct 03 '17 at 02:16

1 Answers1

1

I'll already add here that the output for 225 will be 230 from this algorithm and not 300 as the OP has asked. Reason: My implementation is that way. There is not really any right answer to this question. More than coding this is a designing question.


Idea: Use a map of int to int such that if, key is the number, then value is what should be added to it to get the appropriate number. Extract the digits of the input from the right end and continue to improve the number from its right end moving towards its left one digit at a time.


The map (let's call it additive) would have {key, value} pairs like:

{1, 9}, {2, 8}, ... , {9, 1}, {20, 0}, ..., {90, 10}, ...

Note that you would not need to add every integer to it. Adding only some integers would be enough, if you use the map properly.

Here is the code/pseudocode for you to get proper value from the input number:

int GetProperNumber(int input) {
    //Init a variable to keep track of the sign
    int multiplier = 1;

    //For negative numbers, taking some precaution...
    if (input < 0) {
        input *= -1;
        multiplier *= -1;
    }

    //For cases where the input number is only 1 or 2 digits, some quick checks...
    int numberOfDigits = GetNumberOfDigitsInInput(input);
    if (numberOfDigits == 1) return (input + additive[input]) * multiplier;
    if (numberOfDigits == 2) return (input + additive[input - input/10]) * multiplier;

    //Now, coming to the core of the method
    int divisor = 10; //We'll use it to get the left part from the input
    while (true) {

        //First, get right part of the number
        int inputWithDigitsRemoved = input / divisor;

        //If the leftover part is too small, i.e. we have reached the last digit,
        //then break as we have now rounded the number off pretty well.
        if (inputWithDigitsRemoved <= 9) break;

        int inputWithDigitsMasked = inputWithDigitsRemoved * divisor;
        int right = input - inputWithDigitsMasked;

        //Since the number is still not rounded to the right magnitude, 
        //the result should be further improved.
        if (additive.Contains(right)) input += additive[right];
        divisor *= 10;
    }
    return input * multiplier;
}

Some sample result would be:

Input = 5, Output = 10

Input = 99, Output = 100

Input = 2541, Output = 2600

displayName
  • 13,888
  • 8
  • 60
  • 75