簡體   English   中英

計算負實數值的 Gamma function (C++, Boost)

[英]calculating the Gamma function for negative real values (C++, Boost)

以下無限嚴重需要計算非整數、負數、實數的階乘: 無限嚴重:

(這是一種計算橢圓周長的方法,a 和 b 是半長軸和半短軸,h 定義為:
h = (ab)^2/(a+b)^2)

階乘 function 可以通過 Gamma function 擴展到負值,該 Gamma 是為所有非負整數的實數定義的。

在編寫嚴重的代碼時,我嘗試了 boost::math::factorial 和 boost::math::tgamma ,它只給出了-1(不包括)-1.5 的結果,例如給出一個錯誤。

    #include <iostream>
    #include <boost/math/special_functions/factorials.hpp>

    int main()
    {
        double x;
        double f;
        double tg;

        x = -0.5;
        f = boost::math::factorial<double>(x);
        tg = boost::math::tgamma<double>(x);
        cout << "factorial of " << x << " = " << f << endl;
        cout << "tgamma of " << x << " = " << tg << endl << endl;

        x = -1.5;
        f = boost::math::factorial<double>(x);
        tg = boost::math::tgamma<double>(x);
        cout << "factorial of " << x << " = " << f << endl;
        cout << "tgamma of " << x << " = " << tg << endl << endl;
    
        return 0;
    }

output:

-0.5 = 1 的階乘
-0.5 = -3.54491 的 tgamma
在拋出 'boost::exception_detail::clone_implboost::exception_detail::error_info_injector<std::domain_error >' 的實例后調用終止 what(): function boost::math::tgamma(long double) 中的錯誤:評估 tgamma在負 integer 0. 中止(核心轉儲)

提升階乘: 提升階乘
升壓tgamma: 升壓tgamma

我的問題:

  1. 是否有可以計算其負域的伽馬 function 的替代方案?
  2. 我在上面提到的階乘和 tgamma 函數的實現域的鏈接的 boost 文檔中找不到。 事實上,我可能只是錯誤地使用它們。 確定什么是域/正確用法的方法是什么?

謝謝。

自 C++11 [1] 以來,伽瑪函數是標准庫的一部分。

用法如下:

#include <cmath>

std::tgamma(-0.5) # -3.5449077
std::lgamma(-0.5) # 1.2655121

您不妨將tgammaltgammaf用於相應的long doublefloat類型。

  1. https://en.cppreference.com/w/cpp/numeric/math

我只是嘗試在 Mac 上使用 g++-10 重現您的問題,使用 boost.math commit hash 87929356790ad0 (當前develop ),但我得到:

factorial of -0.5 = 1
tgamma of -0.5 = -3.54491

factorial of -1.5 = 1
tgamma of -1.5 = 2.36327

因此需要更多信息,Boost 版本、操作系統、編譯器等。

我明白出了什么問題。 boost::math::factorial function 采用unsigned integer的定義

template <class T>
inline T factorial(unsigned i)
{
   return factorial<T>(i, policies::policy<>());
}

這意味着如果你用雙精度調用它,它將被隱式轉換為無符號。 那不是你想要的。 此外, factorial最終在內部使用tgamma ,所以你得到這個:

#include <boost/math/special_functions/factorials.hpp>
#include <iostream>

void foo(long double x) {
    using namespace boost::math;
    try {
        auto f = factorial<long double>(x);
        std::cout << "factorial of " << static_cast<unsigned>(x) << " = " << f << "\n";
    } catch(std::exception const& e) {
        std::cout << "error at " << static_cast<unsigned>(x) << ": " << std::quoted(e.what()) << "\n";
    }
}

int main() {
    std::cout << std::unitbuf;
    foo(-2);
}

最終會這樣做:

#0  boost::math::tgamma<long double, boost::math::policies::policy<boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy> > (a=4294967295, z=...)
    at /home/sehe/custom/boost_1_73_0/boost/math/special_functions/gamma.hpp:1994
No locals.
#1  0x0000555555558eb3 in boost::math::factorial<long double, boost::math::policies::policy<boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy> > (i=4294967294, pol=...)
    at /home/sehe/custom/boost_1_73_0/boost/math/special_functions/factorials.hpp:44
        result = -0.667762310955655363645
#2  0x0000555555558674 in boost::math::factorial<long double> (i=4294967294)
    at /home/sehe/custom/boost_1_73_0/boost/math/special_functions/factorials.hpp:53
No locals.
#3  0x0000555555557792 in foo (x=-2) at /home/sehe/Projects/stackoverflow/test.cpp:7
        f = <invalid float value>
#4  0x000055555555791f in main () at /home/sehe/Projects/stackoverflow/test.cpp:16
No locals.

所以它試圖給你boost::math::factorial<long double> (i=4294967294)

使固定

不要將factorials用於非負整數以外的值。

Live On 編譯器資源管理器

#include <boost/math/special_functions/factorials.hpp>
#include <iostream>

void foo(long double x) {
    using namespace boost::math;
    try {
        auto tg = tgamma<long double>(x);
        std::cout << "tgamma    of " << x << " = " << tg << "\n" << std::endl;
    } catch(std::exception const& e) {
        std::cout << "error at " << x << ": " << std::quoted(e.what()) << std::endl;
    }
}

int main() {
    for (auto x : { 1., 2., 3., 4., 5., -.2, -2., -.5, -1.5 })
        foo(x);
}

印刷:

tgamma    of 1 = 1

tgamma    of 2 = 1

tgamma    of 3 = 2

tgamma    of 4 = 6

tgamma    of 5 = 24

tgamma    of -0.2 = -5.82115

error at -2: "Error in function boost::math::tgamma<long double>(long double): Evaluation of tgamma at a negative integer -2."
tgamma    of -0.5 = -3.54491

tgamma    of -1.5 = 2.36327

可以理解的是,它在-2處溢出,但這是正確的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM