在 lambda 捕获中传递 callable
Passing callable in lambda capture
正在阅读 SICP's section about "Formulating Abstractions with Higher-OrderFunctions" I was curious to implement a simple, root solving procedure using Newtons' C++ 中的方法。
但是我的实现有问题,但我无法弄清楚原因。代码可以编译,但由于 fixedPoint 函数内的循环递归无法到达 MAX_IT,堆栈溢出导致 运行 时间崩溃。我 运行 它处于调试模式,因此尾递归不适用。
问题是 fixedPoint 中的函数 g 从未被正确计算(我总是得到 inf. 结果)。我想我错过了一些关于可调用传递和 lambda 捕获的东西(我尝试在 lambda 中传递 std::function)。下面是 运行 平方根问题的示例代码。
#include <iostream>
#include <functional>
#include <cmath>
static constexpr double DELTA = 0.0000001;
static constexpr int MAX_IT = 50000;
using my_function = std::function<double(double)>;
double derivative(const my_function& f, const double x) {
return (f(x + DELTA) - f(x)) / DELTA;
}
bool isConverge(const double p1, const double p2) {
return std::abs(p1 - p2) < DELTA;
}
double fixedPoint(const my_function& g, double x = 1) {
int itCnt = 0;
std::function<double(double, double)> loop;
loop = [&g, &itCnt, &loop](double x0, double x1) -> double {
if (isConverge(x0, x1) || (++itCnt > MAX_IT)) return x1;
return loop(x1, g(x1));
};
return loop(x, g(x));
}
my_function newtonsMethod(const my_function& f) {
return [&f](double x) -> double {return x - f(x) / derivative(f, x); };
}
double findRoot(const my_function& f) {
return fixedPoint(newtonsMethod(f));
}
double sqRoot(double x) {
return findRoot([x](int y) {return y * y - x; });
}
int main() {
const double num = 133;
std::cout << "Square root " << num << ": " << sqRoot(num) << '\n';
return 0;
}
你的问题是 int
截断双
return findRoot([x](int y) {return y * y - x; });
所以当你计算derivative
时,你得到0。
改为
return findRoot([x](double y) {return y * y - x; });
正在阅读 SICP's section about "Formulating Abstractions with Higher-OrderFunctions" I was curious to implement a simple, root solving procedure using Newtons' C++ 中的方法。
但是我的实现有问题,但我无法弄清楚原因。代码可以编译,但由于 fixedPoint 函数内的循环递归无法到达 MAX_IT,堆栈溢出导致 运行 时间崩溃。我 运行 它处于调试模式,因此尾递归不适用。
问题是 fixedPoint 中的函数 g 从未被正确计算(我总是得到 inf. 结果)。我想我错过了一些关于可调用传递和 lambda 捕获的东西(我尝试在 lambda 中传递 std::function)。下面是 运行 平方根问题的示例代码。
#include <iostream>
#include <functional>
#include <cmath>
static constexpr double DELTA = 0.0000001;
static constexpr int MAX_IT = 50000;
using my_function = std::function<double(double)>;
double derivative(const my_function& f, const double x) {
return (f(x + DELTA) - f(x)) / DELTA;
}
bool isConverge(const double p1, const double p2) {
return std::abs(p1 - p2) < DELTA;
}
double fixedPoint(const my_function& g, double x = 1) {
int itCnt = 0;
std::function<double(double, double)> loop;
loop = [&g, &itCnt, &loop](double x0, double x1) -> double {
if (isConverge(x0, x1) || (++itCnt > MAX_IT)) return x1;
return loop(x1, g(x1));
};
return loop(x, g(x));
}
my_function newtonsMethod(const my_function& f) {
return [&f](double x) -> double {return x - f(x) / derivative(f, x); };
}
double findRoot(const my_function& f) {
return fixedPoint(newtonsMethod(f));
}
double sqRoot(double x) {
return findRoot([x](int y) {return y * y - x; });
}
int main() {
const double num = 133;
std::cout << "Square root " << num << ": " << sqRoot(num) << '\n';
return 0;
}
你的问题是 int
截断双
return findRoot([x](int y) {return y * y - x; });
所以当你计算derivative
时,你得到0。
改为
return findRoot([x](double y) {return y * y - x; });