Algorithm to find the roundest/most beautiful number in a given interval

Started by
5 comments, last by choffstein 16 years, 2 months ago
As the heading says. Intervals are arbitrarily, positive, negative, huge numbers, very very small numbers. That's what I am doing at the moment

    double delta = max - min;
    double deltalog = floor(logarithm(delta,type));

    /* power of the floor of the log of delta
        ... e.g. 4000 -> 1000, 323 -> 100 */
    double biggeststep = power(deltalog,type);

    /* round down the minmum to a multiple of biggeststep */
    double minround = min - fmod(min,biggeststep);

    /* round min down  */
    double nicenumber = minround;

    /* increase nicenumber by one step */
    if (min > nicenumber) {
        nicenumber += biggeststep;
    }
(the logarithm-/power-wrapper-thing deals with BI- and SI-values separately It produces results. Relatively good ones. flaws: - does not prefere .5-values and even values over others - does sometimes not produce a zero, but the interval is [-x,+y] Any ideas to improve this? Thanks in advance
Advertisement
Could you define what "most beautiful number" means.
I've done something like that for a dynamic time scale display. I don't have the code right now, but from the top of my head, it was something like this:

Take the floor of the logarithm of your interval, eg.
double nextSmallerLog = floor(log10(interval));


then calculate the factor this number has to the obtained next smaller logarithmic whole:
double factor = interval / exp10(nextSmallerLog);


and finally choose the nice number based on where you want to divide a decade:
if(factor < 2.5)  niceNumber = exp10(nextSmallerLog) * 2.5;else if(factor < 5.0)  niceNumber = exp10(nextSmallerLog) * 5.0;else  niceNumber = exp10(nextSmallerLog) * 10;


This should round any given interval into numbers like 0.25, 0.50, 1.00, 2.50, 5.00, 10.00, 25.00, 50.00, 100.00, ...

As I said, I'm not quite sure that's the actual code I used, but maybe it does give you an idea about how to proceed.

-Markus-

EDIT: Fixed a stupid spelling error ;)

[Edited by - Cygon on February 22, 2008 12:39:56 AM]
Professional C++ and .NET developer trying to break into indie game development.
Follow my progress: http://blog.nuclex-games.com/ or Twitter - Topics: Ogre3D, Blender, game architecture tips & code snippets.
Thanks for your input.

I adopted your idea, and changed the big if into something better imho.

    factor = pow(0.5,floor(log10(factor/20.0) / log10(0.5)))*20.0;    nicestep = deltalogpower * factor;

This rounds the factor to 10,5.0,2.5,1.25,0.625, ... which produces kick-ass values :).

Thanks a lot.


@Antheus:
"Human preference". No periods, prefer .5 over even over odd values ... and and and.
This is an interesting little gem. Mind if I ask what you are using it for, and what the specific conditions are?

Thanks!
For a "performance"-visualization tool. I need a scales for various purposes.
One is displaying an arbitrary time slice of a program to analyze.
Would you mind posting the entire algorithm and an example or two of how it is used? I think I might be able to apply it to some work that I am doing with psychological interpretations of numbers in the stock market...

This topic is closed to new replies.

Advertisement