我怎样才能转换这个C++函数从使用 long 到其他类型?

发布于 2024-08-20 23:44:42 字数 1446 浏览 3 评论 0原文

我有一个名为“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:错误:无法使用此语法初始化数组

I have this original C++ function called "s":

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

I've been struggling to convert this function over to using the GMP's mpz type, so that it will allow for arbitrarily long integers.

This is my attempt at it:

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

The whole original program can be found here: http://pastebin.com/mf751592

What am I doing wrong? I seemed to initially have trouble because I couldn't return type mpz_t. So instead, I passed in a pointer to what I want the function to return.

I'm still struggling with it though. Can someone point me in the right direction?

This line: for (mpz_t i, mpz_init(i), mpz_set_str(i, "2", 10); mpz_cmp(i,m)< 0; mpz_add_ui(i, i, 1))
Gives this error: 23: error: cannot initialize arrays using this syntax

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

可爱暴击 2024-08-27 23:44:42

你基本上走在正确的轨道上。但是,两个函数参数都应为 mpz_t 类型。所以标题是这样的:

void s(mpz_t n, mpz_t final)

你不需要在最后加上final=sum。相反,只要在使用 sum 的地方使用 final 即可。另外,

mpz_t i;
for (mpz_init_set_ui(i, 2); mpz_cmp(i,m) < 0; mpz_add_ui(i, i, 1))

在 for 循环中执行 do: for 。调用就像:

mpz_t final, n;
mpz_init(final);
mpz_init_set_ui(n, 5);
s(n, final);

编辑:正如 Steve314 所指出的,您应该为每个 mpz_init 执行 mpz_clear 。由于您可以让调用者通过 initted Final,因此需要清理 m、temp 和 i。

You were mostly on the right track. However, both function parameters should be of type mpz_t. So the header's like:

void s(mpz_t n, mpz_t final)

You don't need final = sum at the end. Instead, just use final everywhere you use sum. Also, do:

mpz_t i;
for (mpz_init_set_ui(i, 2); mpz_cmp(i,m) < 0; mpz_add_ui(i, i, 1))

for the for loop. A call is like:

mpz_t final, n;
mpz_init(final);
mpz_init_set_ui(n, 5);
s(n, final);

EDIT: As noted by Steve314, you should do a mpz_clear for every mpz_init. Since you can have the caller pass an initted final, that leaves cleaning up m, temp, and i.

梦在深巷 2024-08-27 23:44:42

你的最后一行应该是 *final = sum;否则,您将更改指针指向的地址。

或者使用参考代替:)

Your last line should be *final = sum; Otherwise you change the address to which your pointer points.

Or use reference instead :)

Smile简单爱 2024-08-27 23:44:42

只需在 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)) {
   ...
}

Just declare and initialize i before the for loop instead..

mpz_t i;
mpz_init(i);
mpz_set_str(i, "2", 10);

for (; mpz_cmp(i,m)< 0; mpz_add_ui(i, i, 1)) {
   ...
}
幽蝶幻影 2024-08-27 23:44:42

gmp 是一个纯 C 库,IIRC。

值得关注的领域包括缺乏 mpz_t 变量的清理(C 中没有析构函数),以及最后一行中赋值运算符的使用(C 中没有重载运算符 - 这实际上是 POD memcpy)。 IIRC,mpz_clear是整数清理函数。

将分配替换为 mpz_set 或 mpz_swap - 如果您要删除临时数据,则交换会更有效,因为它可以避免复制底层数据结构。

不过,真正能解释的就是内存泄漏。

我的下一个怀疑领域是使用相同变量作为输入和输出的调用。我不了解 gmp,但是很多库在传递指针时不喜欢这样 - 输入参数在使用时会发生变化(因为它也是输出),从而导致损坏。可能需要一些额外的临时材料。

gmp is a pure C library, IIRC.

Areas of concern include a lack of cleanups of the mpz_t variables (no destructors in C), and the use of the assignment operator in the last line (no overloaded operators in C - this is effectively a POD memcpy). IIRC, mpz_clear is the integer cleanup function.

Replace the assigment with either mpz_set or mpz_swap - swap being more efficient if you're about to delete the temporary as it avoids copying underlying data structures.

Still, all that would really explain is memory leakage.

My next area of suspicion would be the calls where the same variable is used both as an input and an output. I don't know about gmp, but a lot of libraries don't like this when passing pointers - the input parameter gets changed while being used (since it is also the output), causing corruption. A few extra temporaries may be needed.

◇流星雨 2024-08-27 23:44:42

尝试使用模板

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

Try using templates

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文