用C打印位置数字系统

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

000 001 010 011 ... 111 

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

 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) 10,2 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,然后重复。

最后,记得释放calloc分配的内存。

 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; } 

还有更多方法可以解决这个问题。 欢乐时光!