我有一个名为“s”的原始C ++函数:
long s(long n) {
long sum = 0;
long m;
m = (long) sqrt(n);
for (long i = 2; i < m; i++)
if ((n % i) == 0) sum += (i + (n/i));
if (n>1) sum += 1;
if ((m*m) == n) sum += m;
return sum;
}
我一直在努力将此功能转换为使用GMP的mpz类型,因此它将允许任意长整数。
这是我的尝试:
void s(mpz_t n, mpz_t *final)
{
mpz_t sum;
mpz_t m;
mpz_t temp;
mpz_init (sum);
mpz_init (m);
mpz_init (temp);
mpz_set_str (sum, "0", 10);
mpz_sqrt(m, n);
for (mpz_t i, mpz_init(i), mpz_set_str(i, "2", 10); mpz_cmp(i,m)< 0; mpz_add_ui(i, i, 1))
{
mpz_mod(temp, n, i);
if (mpz_cmp_si(temp, 0) == 0)
{
// use divexact since we know they are divisable
mpz_divexact(temp, n, i);
mpz_add(temp, temp, i);
mpz_add(sum, sum, temp);
}
}
if (mpz_cmp_si(n, 1) > 0) mpz_add_ui(sum, sum, 1);
mpz_mul(temp, m, m);
if (mpz_cmp(temp, n) == 0) mpz_add(sum, sum, m);
final = sum;
}
可以在此处找到整个原始程序:http://pastebin.com/mf751592
我做错了什么?我似乎最初遇到麻烦,因为我无法返回类型mpz_t。所以相反,我传入了一个指向我希望函数返回的指针。
尽管如此,我仍然在努力。有人能指出我正确的方向吗?
这一行: for (mpz_t i, mpz_init(i), mpz_set_str(i, "2", 10); mpz_cmp(i,m)< 0; mpz_add_ui(i, i, 1))
给出此错误:23:错误:无法使用此语法初始化数组
答案 0 :(得分:3)
你大部分时间都在正确的轨道上。但是,两个函数参数都应该是mpz_t类型。所以标题就像:
void s(mpz_t n, mpz_t final)
最后你不需要final = sum。相反,只要在使用总和的任何地方使用final。另外,请执行:
mpz_t i;
for (mpz_init_set_ui(i, 2); mpz_cmp(i,m) < 0; mpz_add_ui(i, i, 1))
for for循环。通话就像:
mpz_t final, n;
mpz_init(final);
mpz_init_set_ui(n, 5);
s(n, final);
编辑:正如Steve314所说,你应该为每个mpz_init做一个mpz_clear。因为你可以让调用者通过一个初始的final,这样可以清理m,temp和i。
答案 1 :(得分:1)
你的最后一行应该是* final = sum;否则,您可以更改指针指向的地址。
或者改为使用引用:)
答案 2 :(得分:1)
只需在for循环之前声明并初始化i ..
mpz_t i;
mpz_init(i);
mpz_set_str(i, "2", 10);
for (; mpz_cmp(i,m)< 0; mpz_add_ui(i, i, 1)) {
...
}
答案 3 :(得分:1)
gmp是一个纯粹的C库,IIRC。
关注的领域包括缺少mpz_t变量的清理(C中没有析构函数),以及在最后一行使用赋值运算符(C中没有重载运算符 - 这实际上是POD memcpy)。 IIRC,mpz_clear是整数清理函数。
使用mpz_set或mpz_swap替换该分配 - 如果您要删除临时数据,则交换效率更高,因为它可以避免复制基础数据结构。
但是,所有这些都可以解释为内存泄漏。
我怀疑的下一个领域是将同一个变量用作输入和输出的调用。我不知道gmp,但是很多库在传递指针时都不喜欢这样 - 输入参数在被使用时会被更改(因为它也是输出),导致损坏。可能需要一些额外的临时工具。
答案 4 :(得分:0)
尝试使用模板
template <class myType>
myType s(myTypen) {
myType sum = 0;
myType m;
m = (myType) sqrt(n);
for (myType i = 2; i < m; i++)
if ((n % i) == 0) sum += (i + (n/i));
if (n>1) sum += 1;
if ((m*m) == n) sum += m;
return sum;
}