GSL中的一维求根

一维求根

    本章描述了寻找任意一维函数根的程序。本库提供了用于各种迭代求解器和收敛测试的低级组件。用户可以将这些组合起来以实现所需的解决方案,并完全访问迭代的中间步骤。每一类方法都使用相同的框架,因此您可以在运行时在求解器之间切换,而不需要重新编译程序。求解器的每个实例都跟踪自己的状态,允许在多线程程序中使用求解器。

    头文件gsl_root .h包含根查找函数和相关声明的原型。

36.1 概述

一维寻根算法可分为两类:根交叉法和根修正法。通过交叉求根的算法保证收敛。根交叉法从已知包含一个根的有界区域开始,不断地缩小这个有界区域的大小,直到它将根封闭到所需的误差精度。这为根的位置提供了一个严格的错误估计。

根修正法技术试图提高对根的初步猜测。这个算法只有在开始时“足够接近”一个根,并且为了速度牺牲了严格的误差范围时才收敛。通过近似一个函数在根附近的行为,他们试图找到一个初始猜想的高阶改进。当函数的行为与算法相匹配且初始猜测良好时,根修正法可以确保快速收敛。

在GSL中,这两种算法都在类似的框架中使用。用户为算法提供高级驱动程序,本库提供每个步骤所需的单独函数。迭代有三个主要阶段,步骤是,

• 为算法T初始化解决器状态s

• 使用迭代T更新s

• 测试收敛性,必要时重复迭代。

    根交叉法求解器的状态保存在gsl_root_fsolver结构体中。更新过程只使用函数求值(而不是导数)。根修正法求解器的状态保存在gsl_root_fdfsolver结构体中。更新要求用户同时提供函数及其导数(因此命名为fdf)。

36.2 警告说明

    注意,根查找函数一次只能搜索一个根。当搜索区域中有多个根时,将返回找到的第一个根;然而,很难预测这将是哪一个根。在大多数情况下,如果您试图在一个有多个根的区域中找到一个根,不会报告错误。

必须注意,当一个函数可能有多个根时(如f(x) = (xx0)2或f(x) = (xx0)3。不可能在偶数多重根上使用根交叉法。对于这些算法,初始区间必须包含过零点,其中函数在区间的一端为负,在另一端为正。偶数重的根不与零相交,而只是瞬间接触它。基于根交叉法仍然适用于奇多重根(例如三次根,五次根,…)。根修正法通常适用于更高的根数,但收敛速度较低。在这种情况下,Steffenson算法可以用来加速多重根的收敛。

虽然不是绝对要求f在搜索区域内有一个根,但不应该随意使用数值求根函数来检查根的存在性。有更好的方法来做这个事情,因为很容易出现数值求根查找器失败的情况,所以在您不太了解的函数上采用根查找器不是一个好主意。一般来说,最好是在寻找根之前通过作图直观地检查函数。

36.3 初始化求解器

gsl_root_fsolver

    这是一个不需要使用导数的方法来查找根的工作空间。

gsl_root_fdfsolver

这是一个需要使用导数的方法来查找根的工作空间

gsl_root_fsolver * gsl_root_fsolver_alloc(const gsl_root_fsolver_type * T)

    本函数返回一个指针,指向新分配的T类型求解器实例。例如,下面的代码创建了一个二分求解器实例:

const gsl_root_fsolver_type * T = gsl_root_fsolver_bisection;

gsl_root_fsolver * s = gsl_root_fsolver_alloc (T);

如果没有足够的内存来创建求解器,则函数返回一个空指针,错误处理程序将使用错误代码GSL_ENOMEM调用。

gsl_root_fdfsolver * gsl_root_fdfsolver_alloc(const gsl_root_fdfsolver_type * T)

    本函数返回一个指针,指向新分配的基于派生的T型求解器实例。例如,下面的代码创建了一个Newton-Raphson求解器实例:

const gsl_root_fdfsolver_type * T = gsl_root_fdfsolver_newton;

gsl_root_fdfsolver * s = gsl_root_fdfsolver_alloc (T);

如果没有足够的内存来创建求解器,则函数返回一个空指针,错误处理程序将使用错误代码GSL_ENOMEM调用。

int gsl_root_fsolver_set(gsl_root_fsolver * s, gsl_function * f, double x_lower,

double x_upper)

    本函数用函数f和初始搜索区间[x_lower, x_upper]初始化,或重新初始化,一个已经存在的求解器s。

int gsl_root_fdfsolver_set(gsl_root_fdfsolver * s, gsl_function_fdf * fdf, double root)

    本函数用函数和导数fdf以及初始的猜想根初始化,或重新初始化,一个已经存在的求解器。

void gsl_root_fsolver_free(gsl_root_fsolver * s)

void gsl_root_fdfsolver_free(gsl_root_fdfsolver * s)

    这些函数释放了与求解器s有关的所有内存。

const char * gsl_root_fsolver_name(const gsl_root_fsolver * s)

const char * gsl_root_fdfsolver_name(const gsl_root_fdfsolver * s)

    这些函数返回一个指向求解器名称的指针。例如:

printf ("s is a '%s' solver\n", gsl_root_fsolver_name (s));

    打印出类似如下内容:s is a 'bisection' solver.

GSL(GNU Scientific Library)是一个开源的科学计算库,其中包含了许多数学、统计和物理学方面的工具和函数,可以用于各种科学计算领域。 一维小波变换(DWT)是一种信号处理技术,它可以将信号分解成不同的频率子带,每个子带都包含了不同频率的信息。DWT 在信号压缩、图像处理、声音处理等方面都有广泛的应用。 在 GSL 中,有一个专门用于一维小波变换的模块,它提供了基于 Haar、Daubechies、Symlets、Coiflets 和 Biorthogonal 等小波函数族的 DWT 实现。下面是一个基于 Haar 小波函数的一维小波变换的示例代码: ```c #include <stdio.h> #include <gsl/gsl_wavelet.h> int main() { // 定义输入信号 double data[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}; int n = sizeof(data) / sizeof(double); // 定义小波变换参数 gsl_wavelet_workspace *w = gsl_wavelet_workspace_alloc(n); gsl_wavelet *wv = gsl_wavelet_alloc(gsl_wavelet_haar, 2); gsl_wavelet_transform_direction dir = GSL_WAVELET_FORWARD; // 进行小波变换 gsl_wavelet_transform(wv, data, 1, n, dir, w); // 输出变换后的结果 printf("DWT coefficients:\n"); for (int i = 0; i < n; i++) { printf("%g ", data[i]); } printf("\n"); // 释放内存 gsl_wavelet_free(wv); gsl_wavelet_workspace_free(w); return 0; } ``` 在上面的示例代码中,我们首先定义了一个长度为 8 的输入信号 data,然后定义了一个 Haar 小波函数族的小波变换对象 wv 和一个工作空间 w,接着调用 gsl_wavelet_transform 函数进行小波变换,最后输出变换后的结果。 需要注意的是,小波变换的结果保存在原始数据数组 data 中,因此在输出变换后的结果时,我们直接遍历 data 数组即可。 当然,如果你想使用其他小波函数族进行小波变换,只需要在定义小波变换对象 wv 时选择对应的小波函数族即可。例如,如果要使用 Daubechies 小波函数族进行小波变换,可以将上面的代码中的 gsl_wavelet_haar 替换为 gsl_wavelet_daubechies,同时将小波变换对象 wv 的第二个参数从 2 改为 4(因为 Daubechies 小波函数族有 4 个可选的参数)即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值