首页
论坛
课程
招聘
[分享]《探索现代化C++》泛读笔记摘要9
2022-9-15 09:30 3756

[分享]《探索现代化C++》泛读笔记摘要9

2022-9-15 09:30
3756

《探索现代化C++》泛读笔记摘要9

Chapter 3 通用编程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class psc_f
{
public:
    psc_f(double alpha) : alpha{alpha} {}
    double operator() (double x) const
    {
        return sin(alpha * x) + cos(x);
    }
private:
    double alpha;
};
 
template <typename F, typename T>
T inline fin_diff(F f, const T& x, const T& h)
{
    return (f(x+h) - f(x)) / h;
}

上回的求解高阶近似导数还没讲完,因为fin_diff仍然是一个三元函数。

 

理论上我们需要一个一元函数,于是我们根据需要定义一元仿函数来解决这个问题。

 

导数(Derivative)是微积分中的重要基础概念。

1
2
3
4
5
6
7
8
9
10
11
12
13
template <typename F, typename T>
class derivative
{
public:
    derivative(const F& f, const T& h) : f{f}, h{h} {}
    T operator()(const T& x) const
    {
        return ( f(x+h) - f(x) ) / h;
    }
private:
    const F& f;
    T h;
};

调用例子如下:

1
2
3
4
5
6
7
8
9
using d_psc_f = derivative<psc_f,double>;
psc_f psc_o{1.0}; // psc_f的一个对象,sin ax + cosx 此时 a = 1.0
d_psc_f d_psc_o{psc_o,0.001}; // h = 0.001
 
cout<<"der. of sin(x) + cos(x) at 0 is "<<d_psc_o(0.0)<<'\n';
 
using dd_psc_f = derivative<d_psc_f,double>;
dd_psc_f dd_psc_o{d_psc_o,0.001};
cout<<"2nd der. of sin(x) + cos(x) at 0 is "<<dd_psc_o(0.0)<<'\n';

上面的例子中为了求二阶导必须先生成了一个一阶导函数。但是如果用户只想求二阶导函数,而不希望自己生成一阶导函数的话,我们就需要直接定义二阶导函数的仿函数定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<typename F,typename T>
class second_derivative
{
public:
    second_derivative(const F& f, const T& h)
        : h{h}, fp{f, h} {}
    T operator()(const T& x) const
    {
        return ( fp(x+h) - fp(x) ) / h;
    }
private:
    T h;
    derivative<F, T> fp;
};

调用例子

1
second_derivative<psc_f,double> dd_psc_2_o{psc_f(1.0),0.001};

如果我们希望计算3,4,5甚至是n阶导函数呢?一个个定义吗?其实可以采用递归的解法。

 

解法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <unsigned N, typename F, typename T>
class nth_derivative
{
    using prev_derivative= nth_derivative<N-1, F, T>;
public:
    nth_derivative(const F& f, const T& h)
        : h{h}, fp{f, h} {}
    T operator()(const T& x) const
    {
        return ( fp(x+h) - fp(x) ) / h;
    }
private:
    T h;
    prev_derivative fp;
};

为了避免无限递归,我们需要定义一阶导数。

1
2
3
4
5
6
7
8
9
10
11
12
13
template <typename F, typename T>
class nth_derivative <1, F, T>
{
public:
    nth_derivative(const F& f, const T& h) : f{f}, h{h} {}
    T operator()(const T& x) const
    {
        return ( f(x+h) - f(x) ) / h;
    }
private:
    const F& f;
    T h;
};

也可使用继承写法

1
2
3
4
5
6
template <typename F, typename T>
class nth_derivative<1, F, T>
    : public derivative<F, T>
{
    using derivative<F, T >::derivative;
};

现在我们就可以计算n阶导数了,比如22阶。

1
2
nth_derivative<22, psc_f, double> d22_psc_o{psc_f(1.0),
0.00001};

未完待续。


[2022冬季班]《安卓高级研修班(网课)》月薪两万班招生中~

最后于 2022-9-23 20:58 被VirtualCC编辑 ,原因: 逻辑错误
收藏
点赞0
打赏
分享
最新回复 (3)
雪    币: 5610
活跃值: 活跃值 (2082)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
sunsjw 活跃值 1 2022-9-23 18:25
2
0
 error C2953: “nth_derivative<1,F,T>”: 类模板已经定义 
雪    币: 3523
活跃值: 活跃值 (4363)
能力值: ( LV6,RANK:96 )
在线值:
发帖
回帖
粉丝
VirtualCC 活跃值 2022-9-23 20:53
3
0
sunsjw error C2953: “nth_derivative”: 类模板已经定义
继承写法和特化写法取其一
雪    币: 5610
活跃值: 活跃值 (2082)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
sunsjw 活跃值 1 2022-9-24 08:56
4
0
VirtualCC 继承写法和特化写法取其一
多谢,已经搞定了。
游客
登录 | 注册 方可回帖
返回