假设C中有一个uint8_t
数组,数组大小为10.我想在数组中生成所有可能的二十进制组合。
这可以用10个嵌套循环实现,每个元素对应一个元素。但是,当您不知道大小时,则无法动态更改嵌套循环的数量。
是否有任何递归方法,以便您可以将此80位视为单个数字并从000000000 .....计数到1111111111 ....其中0和1的数量等于80?
我考虑过GNU gmp,但最大的数字是1024位,你不能将它们作为代表实际数字的简单位来访问。
我想做的只是一个大计数器,从0到2 ^ 80但在数组内部。
我想举个例子。具有两个字节的uint8_t数组:
| 00000000 | 00000000 |
| 00000000 | 00000001 |
| 00000000 | 00000010 | 。 。
| 00000000 | 11111111 |
| 00000001 | 00000000 |
| 00000001 | 00000001 |
| 00000001 | 00000010 |
。 。
#include <gmp.h>
#include <stdio.h>
#include <assert.h>
int main()
{
mpz_t n;
int flag;
//Initialize the number.
mpz_init(n);
mpz_set_ui(n,0);
//Add one to the number */
mpz_add_ui(n,n,1); /* n = n + 1 */
}
您如何访问数字n并将内容复制到您的数组?
memcpy(array, &n, 10) ?
答案 0 :(得分:2)
至少在这个宇宙中,你想要做的事是不可能的。
所有80位组合与最多2⁸⁰的所有数字相同 - 这是非常大数字。
正如您已经注意到的那样,这些值中的每一个都将具有10B的内存需求 - 总计
10 B * 2⁸⁰ = 12089258196146291747061760 B
= 10 B * 2⁵⁰Gi
= 10 * 2⁴⁰ TiB
或换句话说,这是大约5.5万亿SSD,每个容量为2太字节。
让每个SSD重约80g,然后这相当于439,804,651吨的质量。
因为你有点顽固:即使你没有将它存储在RAM或磁盘上,也不可能完成:这里是你的&图表#34; N字节数组中的二进制组合&#34;问题。请注意,y轴的单位为10 ^ 28。
并且因为它没有实际帮助,使用对数y轴:
假设您的PC每秒可以通过十亿个这样的阵列,这就是它需要花费的时间:
因此,对于七字节数组,只需生成数组并立即丢弃它们将花费两年多的时间。你的10 B阵列需要大约3800万年的CPU时间。祝你好运!
无论如何,递归是最糟糕的算法选择,你可以采用for
循环并计算。这里没有歧义,这将与GMP完美配合。我不知道你做错了什么。学习使用GMP:
mpz_t number, limit;
mpz_init_set_ui(number, 0UL); //first value
mpz_init_set_ui(limit, 2UL); // limit=2
mpz_pow_ui (limit,limit,80); // limit=2**80
while(mpz_cmp(number,limit) < 0) { // while number smaller limit
mpz_out_str(stdout, 2, number);
mpz_add_ui(number, number, 1UL); //increase number
}
number
现在获取所有可能的2 ^ 80个值,并以二进制形式打印。从理论上讲。
答案 1 :(得分:2)
您可以使用类似下面的代码。
但请记住,效率不高。如果您想获得更好的性能,请使用unsigned long long
s。
替代解决方案是使用现有的库,如GMP。
#include <stdio.h>
#include <stdint.h>
#define SZ 10
int main(void)
{
uint8_t arr[SZ];
for (int i = 0; i < SZ; i++)
arr[i] = 0;
for (int i = 0; i < SZ*2; i++)
putchar('0');
putchar('\n');
while (1)
{
for (int i = 0; i <= SZ; i++)
{
if (i == SZ)
goto stop;
arr[i]++;
if (arr[i] != 0xff)
break;
}
const char *digits = "0123456789abcdef";
for (int i = SZ-1; i >= 0; i--)
{
putchar(digits[(arr[i] >> 4) & 0xf]);
putchar(digits[arr[i] & 0xf]);
}
putchar('\n');
}
stop:
puts("Done! Wow, you're still alive?");
}
答案 2 :(得分:1)
这是未经检查的,未经优化的代码,有点运气可能会做你想要的。
void add(uint8_t* in1,
uint8_t* in2,
uint8_t* out,
size_t length)
{
uint8_t carry = 0;
for (size_t i = 0;
i < length;
++i)
{
uint16_t res = in1[i] + in2[i] + carry;
out[i] = (uint8_t)(res & 0xff);
carry = res >> 8;
}
}
答案 3 :(得分:1)
快速而肮脏的C解决方案:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
typedef
struct {
size_t size;
uint8_t data[];
} bignum_t;
bignum_t *bn_new(size_t size)
{
// assert size>0
bignum_t *new=malloc(sizeof *new + sizeof(uint8_t[size]));
if (new==NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
new->size=size;
memset(new->data,0,size);
return new;
}
void bn_free(bignum_t *bn)
{
free(bn);
}
bool bn_next(bignum_t *bn)
{
size_t i;
for(i=0; i<bn->size; ++i)
if (bn->data[i]==0xFF)
bn->data[i]=0;
else
break;
if (i==bn->size) return false;
bn->data[i]++;
return true;
}
void bn_print(bignum_t *bn)
{
putchar('[');
for(size_t i=0; i<bn->size; ++i)
printf(" %02X", bn->data[i]);
printf(" ]");
}
int main(void)
{
bignum_t *bn=bn_new(10);
do {
bn_print(bn);
putchar('\n');
} while (bn_next(bn));
bn_free(bn);
return 0;
}
不要期待看到这个节目的结束。
答案 4 :(得分:1)
这是非常可行的。你需要:
这一切都可以在一个功能中完成。在最坏的情况下,堆栈只需要递归到字节数(10个字节= 10个堆栈递归)。
这是我之前准备的。它支持任意数量的字节,尽管它只使用三个字节来让自己看到它运行到最后。
"true"
答案 5 :(得分:0)
这是解决问题的简单方法,打印每个数字的二进制等效值。
尽管已经提出了一些解决方案,但我的是打印二进制的解决方案,它是递归的。
#include <stdio.h>
#include <stdint.h>
void Print(uint8_t *, int);
void IncrementLoop(uint8_t *arr, int sz);
int GetBit(uint8_t *arr, int idx);
int main()
{
uint8_t ca[2] = {0xFF, 0};
IncrementLoop((uint8_t *)ca, 16);
return 0;
}
void IncrementLoop(uint8_t *arr, int sz)
{
int number_of_bytes = sz / 8;
int count = 0;
while((*arr) == (uint8_t)0xFF)
{
++arr;
++count;
if(count >= number_of_bytes)
{
return;
}
}
(*arr) += 1;
for(;count;--count)
{
--arr;
(*arr) &= 0;
}
Print(arr, sz);
IncrementLoop(arr, sz);
}
void Print(uint8_t *arr, int sz)
{
while(sz)
{
printf("%d", GetBit(arr,sz-1));
--sz;
}
printf("\n");
}
int GetBit(uint8_t *arr, int idx)
{
return (1 & (arr[(idx/8)] >> (idx % 8)));
}