用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; }
还有更多方法可以解决这个问题。 欢乐时光!