【翻译】用于科学计算的 C++11/14 新特性之五
总结 C++11/14 中与科学计算相关的新特性。
原文地址 www.numbercrunch.de
【翻译】用于科学计算的 C++11/14 新特性之五
$\lambda$ functions
匿名函数,通常称为 $\lambda$ 函数,是科学编程语言(例如 Maple 和 Matlab)的常见特性。它们在需要将其他函数作为参数的函数中特别有用。例如,数值求根算法需要指定一个函数作为输入参数。
C++11 将 $\lambda$ 函数引入到了 C++ 中,而在 C++14 中它们得到了扩展,变得更加灵活。$\lambda$ 函数可以像仿函数一样赋值给变量。$\lambda$ 函数相对于仿函数的主要优势在于它们可以在需要的地方定义。此外,$\lambda$ 函数捕获当前作用域中的变量,因此它们代表了一个闭包。
$\lambda$ 函数的语法基本上有以下形式:
1
[ capture-list ] ( params ) -> ret { body }
可能为空的捕获列表指定了哪些变量被捕获,以及它们是如何被捕获的(按值或按引用)。然后指定参数和返回类型,接着是函数体的定义。如果函数体只包含一个带有表达式的单一返回语句,则可以省略返回类型。
$\lambda$ 函数的使用可能最好是通过提供一个具体的例子来解释。以下是一个通用的求根算法(试错法)的实现,它在某个区间内寻找某个函数的根。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cmath>
#include <limits>
template<typename T, typename F>
T regula_falsi(T s, T t, F f) {
typedef enum { none, left, right } side_t;
side_t side(none);
// starting values at endpoints of interval
T fs = f(s);
T ft = f(t);
T r;
for (int n = 0; n < std::numeric_limits<T>::digits + 2; ++n) {
r = (fs * t - ft * s) / (fs - ft);
if (std::abs(t - s) < std::numeric_limits<T>::epsilon() * std::abs(t + s))
break;
T fr = f(r);
if (fr * ft > 0) { // fr and ft have same sign, copy r to t
t = r;
ft = fr;
if (side == left)
fs /= 2;
side = left;
}
else if (fs * fr > 0) { // fr and fs have same sign, copy r to s
s = r;
fs = fr;
if (side == right)
ft /= 2;
side = right;
}
else { // fr*f_ very small (looks like zero)
break;
}
}
return r;
}
int main() {
// assign lambda function to variable and use afterwards
auto f = [](double x) { return std::cos(x) - x * x * x; };
double x0 = regula_falsi(0., 1., f);
// specify lambda function directly as an argument
double x1 = regula_falsi(0., 3., [](double x) { return std::cos(x); });
std::cout << std::setprecision(12)
<< x0 << '\n'
<< x1 << '\n';
return 0;
}
本文由作者按照 CC BY 4.0 进行授权