C ++ Durand-Kerner根查找算法与GMP崩溃,但不与长双

时间:2016-09-07 14:40:55

标签: c++ algorithm gmp

我正在尝试一种基于Durand-Kerner的寻根算法,我需要它的订单多项式可能高达50,系数超过long doublelong long,所以我我正在尝试(第一次)GMP

现在,我把这个程序作为一个测试,这就是为什么main()就是这样(加上我不是一个高级程序员),如果我不涉及GMP,它就有效,所以我认为在我的实现中有些东西会让它崩溃。使用Codeblock的调试器,它指向gmpxx.h内部的一些行和f()的函数,sum +=行。

这里是代码,减去多项式系数的产生(这里是一个简单的循环):

#include <iostream>
#include <vector>   // std::vector
#include <complex>
#include <cmath>
#include <iomanip>  // std::setprecision
#include <gmpxx.h>

typedef std::complex<mpf_class> cplx;

// x!
mpz_class fact(const unsigned int &x)
{
    mpz_class z {1};
    for (unsigned int i=1; i<=x; ++i)
        z *= i;
    return z;
}

// 2^n
mpz_class pwr2(const unsigned int &n)
{
    mpz_class z {1};
    for (unsigned int i=0; i<n; ++i)
        z *= 2;
    return (n == 0 ? 1 : z);
}

void bessel(std::vector<mpz_class> &a, const unsigned int &N)
{
    for (unsigned int i=0; i<=N; ++i)
        a[i] = fact(N + i) / fact(N - i) / fact(i) / pwr2(i);
    //return *a;
}

// Definition for f(x), will be called for every iteration
cplx f(const std::vector<mpz_class> &coeff, const cplx &xterm)
{
    cplx sum {0, 0};
    cplx factor {1, 0};
    for (unsigned int k=coeff.size(); k>=0; --k)
    {
        sum += static_cast<cplx>(coeff[k]) * factor;
        factor *= xterm;
        std::cout<<sum<<'\n';
    }
    return sum;
}

// Denominator, product of differences. root is the current root's value
cplx prod(const std::vector<cplx> &roots, const cplx &root)
{
    cplx product {1.0, 0};
    for (unsigned int k=0; k<roots.size(); ++k)
    {
        // Skip if an element of the matrix == current root
        if (roots[k] == root)
            product = product;
        else
            product *= root - roots[k];
    }
    return product;
}

int main()
{
    std::cout << "N=";
    unsigned int N;
    double eps {1e-10}; // relative error
    std::cin >> N;
    std::cout << std::setprecision(16);

    // Declaring arrays for coefficients, initial and final roots
    unsigned int arraySize {N + 1};
    std::vector<mpz_class> coeffs;
    std::vector<cplx> initial;
    std::vector<cplx> roots;
    coeffs.resize(arraySize);
    initial.resize(arraySize);
    roots.resize(arraySize);
    // Keep track of number and maximum numbers of iterations.
    unsigned int maxIter {200};
    unsigned int iters {0};

    for (unsigned int k=0; k<arraySize; ++k)
    {
        coeffs[k] = k+1;
        std::cout << coeffs[k] << " ";
    }
    std::cout << '\n';

    // Initialize the seed roots
    for (unsigned int k=0; k<N; ++k)
        initial[k] = pow(cplx(0.6, 0.8), k);
    // Temporary array to hold next iteration's values
    bool delta[N];
    mpf_class tmp[N];
    while (iters <= maxIter)
    {
        for (unsigned int k=0; k<N; ++k)
        {
            roots[k] = initial[k] - f(coeffs, initial[k]) / prod(initial, initial[k]);
        }
        // Calculate the abs() average of the temporary roots
        bool test {1};
        for (unsigned int k=0; k<N; ++k)
        {
            tmp[k] = fabs(initial[k] - roots[k]);
            delta[k] = tmp[k] <= eps;
            test *= delta[k];
            //test *= fabs(initial[k] - roots[k]) <= eps;
            //std::cout << tmp[k] << " ";
        }
        //std::cout << '\n';
        // Check if eps has been reached
        if (test)
            break;
        // if not, initial roots take current roots' value
        for (unsigned int k=0; k<N; ++k)
            initial[k] = roots[k];
        ++iters;
    }
    /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (unsigned short k=0; k<N; ++k)
        std::cout << tmp[k] << " ";
    std::cout << "\n\n";
    for (unsigned short k=0; k<N; ++k)
        std::cout << initial[k] << "\n";
    std::cout << iters << "\n";

    return 0;
}

std::cout函数中的f()行只有在循环内部才会被打印,否则它会赢得,所以错误必须有一些连接,但我&# 39;我担心它会超过我的头脑。有人可以帮我解决这个错误吗?让我感到满意的是,整个算法在标准类型上运行得很好。

这里是callstack:

#0 0x7ffff7951e00   __gmpf_set_z() (/usr/lib/libgmp.so.10:??)
#1 0x404562 __gmp_set_expr<__mpz_struct [1]>(f=0x7fffffffe2f0, expr=...) (/usr/include/gmpxx.h:2114)
#2 0x403661 __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr<__mpz_struct [1], __mpz_struct [1]>(this=0x7fffffffe2f0, expr=...) (/usr/include/gmpxx.h:1844)
#3 0x401d5c f(coeff=std::vector of length 5, capacity 5 = {...}, xterm=...) (/home/xxx/Documents/cpp/Durand_Kerner_gmp/main.cpp:51)
#4 0x40250f main() (/home/xxx/Documents/cpp/Durand_Kerner_gmp/main.cpp:112)

程序开始显示N=,输入4,例如。

1 个答案:

答案 0 :(得分:2)

Gcc可以指出一个重要问题:

Dictionary<string, Customer> cList = new Dictionary<string, Customer>()
{
   ["LoginView"] = new LoginViewModel(),
   ["SignUpView"] = new SignUpViewModel()
};

应避免使用无符号类型,除非您正在创建自己的bigint类型(或可能使用位域)并知道您在做什么。