c - Nicelabel 算法超过 MAX TICKS

标签 c algorithm

我正在使用 Nice Numbers for Graph Labels算法(由 Andrew S. Glassner 编写),但在某些数字上,例如:(最小值:-206.13 最大值:729.02),它返回的 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 时所需的输出= 10 (7 刻度):

enter image description here

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

最佳答案

对于 minmax 特定值 -206.13 和 729.02 范围计算为 1000.00,tick 为 100.00。但在那之后,minmax 被设置为 -300 和 800,从而将范围扩展到 1100.00。你得到了 11 次,共 10 次。解决方案是在设置了 minmax 时再次计算 tick:

...
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);
...

关于c - Nicelabel 算法超过 MAX TICKS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28431265/

相关文章:

c++ - 我在给定程序中哪里错了?

c - 是否可以从 Linux 下的 C 程序中找到屏幕分辨率?

无法跳出循环

c - 我需要一个 ANSI C 格式的实时时钟,其精度可达毫秒?

c++ - 在排序和旋转的数组中搜索

algorithm - 找出数组中角度之间的最大差异

c - 指向 char 数组的指针数组

尝试在 freebsd 中编译系统调用 .c 文件时出现冲突错误

Android SensorManager.java getOrientation 和 getRotationMatrix 算法

javascript - 使用单个字符串 'right' 或 'left' 作为第二个参数旋转二维数组矩阵