使用mpz_t制作pascal的三角形

时间:2010-04-29 19:51:01

标签: c math malloc gmp

嘿,我正在尝试转换我编写的函数来生成一个longs数组,它将Pascal的三角形表示为一个返回mpz_t数组的函数。但是使用以下代码:

mpz_t* make_triangle(int rows, int* count) {
//compute triangle size using 1 + 2 + 3 + ... n = n(n + 1) / 2
*count = (rows * (rows + 1)) / 2;
mpz_t* triangle = malloc((*count) * sizeof(mpz_t));

//fill in first two rows
mpz_t one;
mpz_init(one);
mpz_set_si(one, 1);
triangle[0] = one; triangle[1] = one; triangle[2] = one;

int nums_to_fill = 1;
int position = 3;
int last_row_pos;
int r, i;
for(r = 3; r <= rows; r++) {
    //left most side
    triangle[position] = one;
    position++;

    //inner numbers
    mpz_t new_num;
    mpz_init(new_num);
    last_row_pos = ((r - 1) * (r - 2)) / 2;
    for(i = 0; i < nums_to_fill; i++) {
        mpz_add(new_num, triangle[last_row_pos + i], triangle[last_row_pos + i + 1]);
        triangle[position] = new_num;
        mpz_clear(new_num);
        position++;
    }
    nums_to_fill++;

    //right most side
    triangle[position] = one;
    position++;
}

return triangle;
}

我收到错误说:对于设置三角形中的位置的所有行的赋值不兼容(即:triangle [position] = 1;)。

有谁知道我可能做错了什么?

1 个答案:

答案 0 :(得分:3)

mpz_t被定义为长度为struct __mpz_struct的数组,这会阻止分配。这样做是因为正常的C赋值是浅拷贝,而各种gmp数值类型存储指向需要深度复制的"limbs"数组的指针。您需要使用mpz_setmpz_init_set(或甚至mpz_init_set_si)来分配MP整数,确保在使用前者之前初始化目标。

此外,您应该为每mpz_clear最多拨一次mpz_init(他们就像malloc一样,在这方面是免费的,并且出于同样的原因)。通过在内部循环中调用外部循环mpz_init(new_nom)中的mpz_clear(new_num),您将引入一个在检查make_triangle的结果时很明显的错误。但是,您甚至不需要new_num;初始化triangle的下一个元素,并将其用作mpz_add的目标。

    mpz_init(triangle[position]);
    mpz_add(triangle[position++], triangle[last_row_pos + i], triangle[last_row_pos + i + 1]);

小数值优化:您可以使用加法和减法更新last_row_pos,而不是两次减法,即乘法和除法。看看你是否能弄明白。