2015-02-10 63 views
0

我使用Nice Numbers for Graph Labels算法(由安德鲁·S·格拉斯纳),但对一些数字,如:(分:-206.13最大值:729.02),它返回更蜱比MAX_TICKS尼斯标签算法超过MAX_TICKS

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <math.h> 

#define MARGIN "   " 
#define MARGIN_LEN 10 
#define MAX_TICKS 10 
#define NVALUES 10 
#define WIDTH 70 

static double nice(double range, int round) 
{ 
    double exponent; 
    double fraction; 
    double nicefrac; 

    exponent = floor(log10(range)); 
    fraction = range/pow(10, exponent); 
    if (round) { 
     if (fraction < 1.5) 
      nicefrac = 1.0; 
     else 
     if (fraction < 3.0) 
      nicefrac = 2.0; 
     else 
     if (fraction < 7.0) 
      nicefrac = 5.0; 
     else 
      nicefrac = 10.0; 
    } else { 
     if (fraction <= 1.0) 
      nicefrac = 1.0; 
     else 
     if (fraction <= 2.0) 
      nicefrac = 2.0; 
     else 
     if (fraction <= 5.0) 
      nicefrac = 5.0; 
     else 
      nicefrac = 10.0; 
    } 
    return nicefrac * pow(10, exponent); 
} 

static double calc(double range, int ticks) 
{ 
    double tick; 

    range = nice(fabs(range), 0); 
    tick = nice(range/(ticks - 1), 1); 
    return tick; 
} 

int main(void) 
{ 
    double value[NVALUES], min, max, tick, sum; 
    int ticks, width, wtick, wzero, wcurr; 
    int i, j; 

    srand(time(NULL)); 
    for (i = 0; i < NVALUES; i++) { 
     value[i] = (rand() % 100000)/100.0 - 250.0; 
    } 
    min = max = value[0]; 
    for (i = 0; i < NVALUES; i++) { 
     if (value[i] < min) min = value[i]; 
     if (value[i] > max) max = value[i]; 
    } 
    printf("MIN = %.2f | MAX = %.2f\n", min, max); 
    if (min > 0.0) min = 0.0; 
    if (max < 0.0) max = 0.0; 
    tick = calc(max - min, MAX_TICKS); 
    min = floor(min/tick) * tick; 
    max = ceil(max/tick) * tick; 
    ticks = (int)((max - min)/tick); 
    width = (int)(floor(WIDTH/ticks) * ticks); 
    wtick = (int)(width/ticks); 
    wzero = (int)ceil(((0.0 - min)/(max - min)) * width); 
    printf("MIN = %.2f | MAX = %.2f | TICK = %.2f | TICKS = %d\n", min, max, tick, ticks); 
    printf("\n" MARGIN); 
    sum = min; 
    for (i = 0; i <= ticks; i++) { 
     printf("%-*.*f", wtick, tick == (int)tick ? 0 : 2, sum); 
     sum += tick; 
    } 
    printf("\n" MARGIN); 
    for (i = 0; i <= ticks; i++) { 
     printf("%-*s", wtick, "|"); 
    } 
    printf("\n"); 
    for (i = 0; i < NVALUES; i++) { 
     printf("%*.2f ", MARGIN_LEN - 1, value[i]); 
     wcurr = (int)round(((value[i] - min)/(max - min)) * width); 
     if (value[i] < 0.0) { 
      for (j = 0; j < wzero; j++) 
       printf("%c", j < wcurr ? ' ' : '*'); 
     } else { 
      for (j = 0; j < wcurr; j++) 
       printf("%c", j < wzero ? ' ' : '*'); 
     } 
     printf("\n"); 
    } 
    return 0; 
} 

在这个例子中MAX_TICKS = 10但我得到11蜱:

MIN = -206.13 | MAX = 729.02 
MIN = -300.00 | MAX = 800.00 | TICK = 100.00 | TICKS = 11 

      -300 -200 -100 0  100 200 300 400 500 600 700 800 
      |  |  |  |  |  |  |  |  |  |  |  |  
    729.02     ******************************************** 
    701.07     ****************************************** 
    -84.62    ***** 
    462.44     **************************** 
    387.91     *********************** 
    683.73     ***************************************** 
    631.30     ************************************** 
    146.09     ********* 
    663.66     **************************************** 
    -206.13  ************ 

所需的输出时MAX_TICKS = 107蜱):

enter image description here

如何调整算法以获得<= MAX_TICKS

回答

1

对于minmax具体值-206.13和729.02的范围计算为1000.00,并勾选为100.00。但之后,minmax设置为-300和800,范围扩大到1100.00。你有11个蜱虫。解决方法是将重新计算tickminmax是设置:

... 
if (min > 0.0) min = 0.0; 
if (max < 0.0) max = 0.0; 
tick = calc(max - min, MAX_TICKS); 

min = floor(min/tick) * tick; 
max = ceil(max/tick) * tick; 

if (((max - min)/tick) > MAX_TICKS) { 
    tick = calc(max - min, MAX_TICKS); 
    min = floor(min/tick) * tick; 
    max = ceil(max/tick) * tick; 
} 

ticks = (int)((max - min)/tick); 
... 
+0

谢谢安托,那是我第一次尝试,它按预期工作,但规模也像'-300 -100 100 300 500 700' ,正如你所看到的,'0'不在规模中,现在我使用[this](https://ideone.com/MtYmCC)作为解决方案(当'> MAX_TICKS'时递归调用。谢谢再次;) – 2015-02-10 14:04:30

+0

我更新了解决方案,因为在这些特殊情况下'min'和'max'也必须重新计算,并且刻度将是'-400,-200,0,...,800' – 2015-02-10 14:06:29

+0

是的,在您上次编辑它的作品;) – 2015-02-10 14:11:02