在 C 中打印位置数字系统



我正在尝试编写一个函数来打印具有给定基数和位数的位置数字系统。例如,当 Base = 2 且 nDigits = 3 时,输出必须如下所示:

000
001
010
011
...
111

现在,我试图做一些事情,但我只是失败了。考虑到我不能存储数字,我只需要打印它们,这就是我使用"支持"数组的动态分配的原因。这就是我到目前为止试图做的事情,显然没有做它想要做的事情......我认为唯一正确的部分是打印 Base^nDigits 的所有组合。(b=基数,n=n位数字)。

void printNumeration(int b, int n){
    int i, j=0;
    int *array = calloc(n, sizeof(int));
    if (array == NULL){
        printf("Allocation failed.n");
        exit(0);
    }

    for (i=0; i<pow(b, n); i++){
        for (j=0; j<n; j++){
            printf("%d", array[j]);
            array[j]++;
            if (array[j] == n){
                array[j] = 0;
            }
        }
        printf("n");
    }
}

如果我的完全错误,您还可以提供有关更好解决方案的一些提示。

首先,不要将pow用于整数。 - 至少不是没有四舍五入pow使用不精确的浮点算法来执行幂运算。就在上周有一个问题,因为pow(10, 2)是 99.9999999...截断为 int 的 99 .

也就是说,很可能有一个平台,其中pow(2, 3)如您的示例所示会导致7.999999...;由于双精度通过截断小数转换为整数,这意味着您的代码运行 7 个循环而不是 8 个循环!对于double比较也是如此;8.0 仍然大于 7.999999999999999。因此,我们使用round来确保结果数字正确舍入到最接近的整数值(在本例中为 8.0)。

此外,您还希望事先计算此数字,而不是每次循环迭代。

我们有 2 个内循环。首先打印数字,然后向后工作 - 如果第 k 位等于 b 我们将其设置为 0,我们将 k 减少 1,现在将第 k 位数字增加 1,然后重复。

最后,记得释放卡洛克分配的内存。

void printNumeration(int b, int n) {
    int *digits = calloc(sizeof(int), n);
    int max = round(pow(b, n));
    for (int i = 0; i < max; i ++) {
        for (int j = 0; j < n; j ++) {
            printf("%d", digits[j]);
        }
        int k = n - 1;
        digits[k] ++;
        while (k && digits[k] == b) {
            digits[k] = 0;
            k--;
            digits[k] ++;
        }
        printf("n");
    }
    free(digits);
}

我听不懂你说的80%...

这是一个糟糕的比例。让我解释一下:

您可以递增内部循环中的每个数字。

您可以在内部循环中无条件地增加每个数字,并在必要时将其包装。这意味着您的枚举会同步递增所有数字,从而产生输出,例如 00、11、22、00、11、2、...

您可以连续递增最后一位数字(并计算进位),直到第一个数字换行(想想里程表)......

您可以从全为零的数组开始。打印出来。递增最后一个数字。检查溢出,如果溢出,将其设置为零并递增下一个数字,依此类推。如果最左边的数字溢出,请停止枚举。这就是汽车里程表(英里/公里计数器)的工作原理:

void printnum(int dig[], int n)
{
    static const char *digit = "0123456789abcdefghijklmnopqrstuvwxyz";
    while (n--) putchar(digit[dig[n]]);
    putchar('n');
}
int enumerate(int base, int n)
{
    int dig[100] = {0};
    int count = 0;
    for (;;) {
        int i = 0;
        while (i < n && dig[i] == base) {
            dig[i++] = 0;
            dig[i]++;
        }
        if (i == n) break;
        printnum(dig, n);
        dig[0]++;
        count++;
    }
    return count;
}

或者您可以使用常用代码打印 i,为每次传递打印 cerian 基数的整数。

枚举生成base^n数字。(不过,您可能不应该使用浮点函数pow来计算此幂。您可以像在代码中一样遍历所有这些数字,然后以给定的基数打印出数字。通常的方法(您可以在 SO 上找到无数示例)是从右侧填充数组,并按基数填充后续除法的余数,直到数字为零。在这里,您希望打印所有数字,因此无论零分子如何,都应进行除法n次。

int enumerate(int base, int n)
{
    int max = 1;
    int i;
    for (i = 0; i < n; i++) max *= base;
    for (i = 0; i < max; i++) {
        int buf[n];
        int j = i;
        int m;
        for (m = 0; m < n; m++) {
            buf[m] = j % base;
            j /= base;
        }
        printnum(buf, n);        
    }
    return max;
}

还有更多方法可以解决这个问题。数小时的乐趣!

最新更新