GNU 方式的科学,第一部分
在我过去的几篇文章中,我研究了各种软件包来完成各种科学工作。然而,有时就是没有工具来解决特定的问题。这就是科学的伟大之处。总是有新的事物可以发现和研究。但是,这意味着您需要开发所需的软件工具来进行分析。本文着眼于 GNU 科学库,或 GSL。这个库是例程中的瑞士军刀库,您会在工作中发现它很有用。
首先,您需要获取 GSL 的副本并将其安装在您的系统上。因为它属于 GNU 项目的一部分,所以它托管在 https://gnu.ac.cn/s/gsl。您始终可以从源代码下载和构建,但是所有主要的发行版都应该有可用的软件包。例如,在基于 Debian 的系统上,您需要安装 libgsl0-dev 包来开发您的代码,并安装 gsl-bin 来运行该代码。GSL 旨在用于 C 和 C++,因此您还需要一个编译器。你们大多数人可能已经熟悉 GCC,所以我在这里坚持使用它。
下一步实际上是最后一步。我现在关注编译,以便我可以专注于 GSL 中提供的所有工具。GSL 的所有头文件都存储在一个名为 gsl 的子目录中。因此,例如,如果您想包含 math 头文件,您将使用
#include <gsl/gsl_math.h>
所有函数都存储在一个名为 libgsl.a 或 libgsl.so 的库文件中。您还需要一个库来处理基本线性代数。GSL 提供了一个(在文件 libgslcblas.so 中),但您可以使用自己的库。此外,您需要链接到数学库中。因此,最终的编译和链接命令应如下所示:Garrick,在下面一行。
gcc -o hello_world hello_world.c -lgsl -lgslcblas -lm
对于 GSL 中一些性能关键的函数,有可选的内联版本。要使用这些,您需要在编译命令中包含 -DHAVE_INLINE
。为了帮助解决可移植性问题,GSL 提供了一些仅在某些平台(而非其他平台)上存在的函数。例如,BSD 数学库有一个名为 hypot
的函数。GSL 提供了它自己的版本,名为 gsl_hypot
,您可以在非 BSD 平台上使用它。一些函数既有通用算法,也有针对特定平台优化的版本。这样,如果您在 SPARC 上运行,例如,如果存在针对 SPARC 优化的版本,您可以选择该版本。
您可能想要做的第一件事之一是检查您是否从代码中获得了正确的结果,或者是否存在错误。GSL 在名为 gsl_errno.h 的头文件中提供了许多函数和数据结构。如果一切正常,函数将返回零值。如果在尝试完成请求的操作时出现任何问题,则会返回一个非零值。这可能是实际的错误情况,例如错误的数据类型或内存错误,或者可能是诸如无法在函数调用中收敛到请求的精度之类的条件。这就是为什么您始终需要检查所有 GSL 函数调用的返回值的原因。错误条件下返回的实际值是错误代码,在文件 gsl_errno.h 中定义。它们被定义为以 GSL_
开头的宏。示例包括以下内容
-
GSL_EDOM
— 域错误,当参数未落在函数定义的域内时,函数使用此错误。 -
GSL_ERANGE
— 范围错误,溢出或下溢。 -
GSL_ENOMEM
— 没有可用内存。
该库将仅使用高达 1024 的值。高于此值的值可用于您自己的代码中。还有这些错误代码的字符串版本可用。您可以使用函数 gsl_errno()
将错误代码转换为其文本值。
现在您已经知道如何编译程序以及如何处理错误,让我们开始看看您可以使用 GSL 做什么样的工作。基本数学函数在文件 gsl_math.h 中定义。GSL 的这部分提供了 BSD 数学库中的数学常数集。所有常数都以 M_
开头。以下是其中一些
-
M_PI
— pi。 -
M_SQRT2
— 2 的平方根。 -
M_EULER
— 欧拉常数。
还具有处理无穷大和非数字的功能。三个宏定义了值本身
-
GSL_POSINF
— 正无穷大。 -
GSL_NEGINF
— 负无穷大。 -
GSL_NAN
— 非数字。
还有一些函数可以测试变量
-
gsl_isnan
— 它不是一个数字吗? -
gsl_isinf
— 它是无穷大吗? -
gsl_finite
— 它是有限的吗?
有一个宏可以找到数字的符号。GSL_SIGN(x)
返回 x 的符号:如果为正数则返回 1,如果为负数则返回 –1。如果您有兴趣查看数字是偶数还是奇数,则定义了两个宏:GSL_IS_ODD(x)
和 GSL_IS_EVEN(x)
。如果条件为真,则这些返回 1,如果条件为假,则返回 0。
一系列基本函数是 BSD 数学库的一部分。GSL 为没有本机版本的平台提供了这些函数的版本,包括如下项
-
gsl_hypot
— 计算斜边。 -
gsl_asinh
、gsl_acosh
、gsl_atanh
— 反双曲三角函数。
如果您要计算数字的幂,您将使用 gsl_pow_int(x,n)
,它会给您 x 的 n 次方。对于小于 10 的幂,有特定版本。因此,如果您想找到一个数字的立方,您将使用 gsl_pow_3
。这些非常高效且高度优化。当定义了 HAVE_INLINE
时,您甚至可以内联这些专用函数。
定义了几个宏来帮助您查找数字的最大值或最小值,基于数据类型。基本的 GSL_MAX(a,b)
和 GSL_MIN(a,b)
只是返回数字 a 和 b 的最大值或最小值。GSL_MAX_DBL
和 GSL_MIN_DBL
使用内联函数查找两个双精度数的最大值和最小值。GSL_MAX_INT
和 GSL_MIN_INT
对整数参数执行相同的操作。
当您在计算机上进行任何类型的数值计算时,总是会因舍入和截断而引入错误。这是因为您无法在有限的二进制系统上完全再现数字。但是,如果您想比较两个数字并查看它们是否大致相同怎么办?GSL 提供了函数 gsl_fcmp(x,y,epsilon)
。此函数比较两个双精度数 x 和 y,并检查它们是否在彼此的 epsilon 范围内。如果它们在此范围内,则函数返回 0。如果 x < y,则返回 –1,如果 x > y,则返回 1。
复数在许多科学领域中使用。在 GSL 中,复数数据类型在头文件 gsl_complex.h 中定义,相关函数在 gsl_complex_math.h 中定义。为了存储复数,定义了数据类型 gsl_complex
。这是一个存储两个部分的结构体。您可以使用函数 gsl_complex_rect(x,y)
或 gsl_complex_polar(x,y)
设置值。在第一个中,这表示 x+iy;而在第二个中,x 是半径,y 是极坐标表示中的角度。您可以使用宏 GSL_REAL
和 GSL_IMAG
拉出复数的实部和虚部。有一个函数可用于查找复数的绝对值,gsl_complex_abs(x)
,其中 x 的类型为 gsl_complex。因为复数实际上是由两部分组成的,所以即使是基本的算术也不简单。要进行基本数学运算,您可以使用以下内容
-
gsl_complex_add(a,b)
-
gsl_complex_sub(a,b)
-
gsl_complex_mul(a,b)
-
gsl_complex_div(a,b)
您可以使用 gsl_complex_conjugate(a)
计算共轭,并使用 gsl_complex_inverse(a)
计算逆。
有一些用于基本数学函数的函数。要计算平方根,您将使用 gsl_complex_sqrt(x)
。要计算对数,您将使用 gsl_complex_log(x)
。还有其他几个可用。
提供了三角函数,例如 gsl_complex_sin(x)
。还有用于双曲三角函数以及相关反函数的函数。
现在您已经掌握了基础知识,我的下一篇文章将探讨您可以进行的所有实际科学计算。我将研究统计学、线性代数、随机数和许多其他主题。
科学图片 通过 Shutterstock.com。