Yes. Since lambdas behave just like functors, and you are using template parameters, it will be fine.
Printable View
Yes. Since lambdas behave just like functors, and you are using template parameters, it will be fine.
Updated with lambda functions and boost::lexical_cast. I also decided to go with fp for the derivative name instead of fPrime, and that x is a less arbitrary initial guess than x / 2.
Code:#include <cassert>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include "boost/cstdint.hpp"
#include "boost/lexical_cast.hpp"
template <typename Function1, typename Function2>
double NewtonsMethod(
Function1 f,
Function2 fp,
double x,
double tolerance,
boost::uint32_t maxIterations)
{
assert(tolerance > 0);
assert(maxIterations != 0);
double last;
boost::uint32_t iterations = 0;
do
{
last = x;
x -= f(x) / fp(x);
++iterations;
}
while (std::abs(x - last) > tolerance && iterations != maxIterations);
return x;
}
int main(int argc, char** argv)
{
if (argc != 3)
{
std::cerr << "Usage: " << argv[0] << " n x" << std::endl;
std::cerr << "(Prints the nth root of x)" << std::endl;
return 1;
}
boost::uint32_t n;
double x;
n = boost::lexical_cast<boost::uint32_t>(argv[1]);
x = boost::lexical_cast<double>(argv[2]);
double nthRootOfX = NewtonsMethod(
[n, x] (double v) -> double { return std::pow(v, n) - x; }, // f
[n, x] (double v) -> double { return n * std::pow(v, n - 1); }, // f'
x, // x[0]
10E-6, // tolerance
100); // max iterations
std::cout << nthRootOfX << std::endl;
return 0;
}
Looks nice. The only complaint is that lexical_cast throws if it fails. You should probably intercept this and display an error.
Are you sure the derivative is right, though? Looks like you've missed a "-1".
Ha, every solution brings another problem :-P. I don't know quite what it is about exception handling, but I'm resistant to doing it. I guess I'm more concerned with how my code looks than how the program it produces looks! Maybe I should think twice about those feelings. Here's the new code:
Code:#include <cassert>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include "boost/cstdint.hpp"
#include "boost/lexical_cast.hpp"
template <typename Function1, typename Function2>
double NewtonsMethod(
Function1 f,
Function2 fp,
double x,
double tolerance,
boost::uint32_t maxIterations)
{
assert(tolerance > 0);
assert(maxIterations != 0);
double last;
boost::uint32_t iterations = 0;
do
{
last = x;
x -= f(x) / fp(x);
++iterations;
}
while (std::abs(x - last) > tolerance && iterations != maxIterations);
return x;
}
void UsageErrorMessage(const char* programName)
{
std::cerr << "Usage: " << programName << " n x" << std::endl;
std::cerr << "(Prints the nth root of x)" << std::endl;
}
int main(int argc, char** argv)
{
if (argc != 3)
{
UsageErrorMessage(argv[0]);
return 1;
}
boost::uint32_t n;
double x;
try
{
n = boost::lexical_cast<boost::uint32_t>(argv[1]);
x = boost::lexical_cast<double>(argv[2]);
}
catch (boost::bad_lexical_cast)
{
std::cerr << "Error: Could not convert arguments to numbers" << std::endl;
UsageErrorMessage(argv[0]);
return 1;
}
double nthRootOfX = NewtonsMethod(
[n, x] (double v) -> double { return std::pow(v, n) - x; }, // f
[n, x] (double v) -> double { return n * std::pow(v, n - 1); }, // f'
x, // x[0]
10E-6, // tolerance
100); // max iterations
std::cout << nthRootOfX << std::endl;
return 0;
}