11

I am having trouble getting my function to return a variable properly.

I print the variable that I want to return above the return statement, and it looks fine. Once I attempt to return the value and print it onto the console though it instead prints -nan(ind). I do not understand why this is happening.

I am programming in C++, using Visual Studio. I am using this library to parse strings into expressions: http://www.partow.net/programming/exprtk/index.html

Here is the function and the statement that prints its results:

#include "stdafx.h"
#include "exprtk.hpp"
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>

typedef double T; // numeric type (float, double, mpfr etc...)
typedef exprtk::expression<T>     expression_t;
typedef exprtk::parser<T>             parser_t;
expression_t expression;
parser_t parser;

bool closeEnough(std::string value1, std::string value2, double levelOfSimilarity) {

    if (abs( std::stod(value1) ) - abs (std::stod(value2) ) > levelOfSimilarity) {
        return false;
    }
    else {
        return true;
    }
}

std::string replaceChars2Strings(std::string string, const std::string& start, const std::string& end) {

    size_t init_pos = 0;

    while ((init_pos = string.find(start, init_pos)) != std::string::npos) {
        string.replace(init_pos, start.length(), end);
    }
    return string;
}

double FofX(std::string function, std::string value) {

    std::string newfunction = replaceChars2Strings(function, std::string("x"), value);


    if (!parser.compile(newfunction, expression))
    {
        printf("Something went wrong when the expression was being parsed");
    }

    T result = expression.value();

    return result;
}

double DofFofX(std::string function, std::string value) {

    std::string SDplus = replaceChars2Strings(function, std::string("x"), "(" + value + "+" + "0.00001" + ")");
    std::string SDminus = replaceChars2Strings(function, std::string("x"), "(" + value + "-" + "0.00001" + ")");

    if (!parser.compile(SDplus, expression))
    {
        printf("Something went wrong when Dplus was being parsed");
    }
    T Dplus = expression.value();

    if (!parser.compile(SDminus, expression))
    {
        printf("Something went wrong when Dminus was being parsed");
    }
    T Dminus = expression.value();

    return (Dplus - Dminus) / 0.00002;
}

double newton(std::string function, std::string guess) {
    double guess2;
    //std::cout << "guess:" << guess << std::endl;

    //in here () are taken off so that the compiler can calculate the value of guess 2 easier
    guess2 = std::stod(guess.substr(1, guess.size() - 2)) - FofX(function, guess) / DofFofX(function, guess);

    //std::cout << "guess 2:" << guess2 << std::endl;

    //take the () off of guess before we give it away
    if (closeEnough(guess.substr(1, guess.size() - 2), std::to_string(guess2), 0.001)) {
        std::cout << "final guess  = " << guess2 << std::endl;
        return guess2;
    }
    else {
        //put the () back on before we give it away so that the parser can read things as multiplication right
        newton(function, "(" + std::to_string(guess2) + ")");
    }
}

int main()
{
    std::string function = "x*x";
    //remember to put () around guess
    std::string guess = "(5)";

    double answer = newton(function, guess);

    return 0;
}

When this program runs it prints this:

final guess  = 0.0006105
solution = -nan(ind)

Does anyone have an idea as to what is happening between when I print the final guess and when I print the solution?

11
  • Please give a complete example. Without knowing what FofX, DofFofX, and closeEnough do, it's impossible to know what's going on, and at best you'll get guesses. Commented Apr 17, 2017 at 2:00
  • A minor comment, it's considered bad practice to have a function that takes input in an "unnatural form" (ie, not the most basic form that the function uses.) In your case newton takes in two string parameters, whereas (because you tagged this with C++11) it should more naturally take a function that takes and returns a double, and a double. You can see this awkwardness in the else statement, where you have to re-modify the string in order to pass it back to itself. Commented Apr 17, 2017 at 2:02
  • 2
    You have no return statement in the else branch in the function Commented Apr 17, 2017 at 2:09
  • 1
    @GlenPierce it absolutely is a problem. Commented Apr 17, 2017 at 2:17
  • 1
    @GlenPierce you'll notice that the examples in that website have the recursive function returning void at the top, but when you reach the factorial example, it returns a int and all of the recursive calls contain a return statement. Commented Apr 17, 2017 at 2:23

1 Answer 1

10

The issue was that I wasn't returning the recursive function in my else statement.

The final code looks like this:

// Newtons Method V1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "exprtk.hpp"
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>

typedef double T; // numeric type (float, double, mpfr etc...)
typedef exprtk::expression<T>     expression_t;
typedef exprtk::parser<T>             parser_t;
expression_t expression;
parser_t parser;

bool closeEnough(std::string value1, std::string value2, double levelOfSimilarity) {

    if (abs( std::stod(value1) ) - abs (std::stod(value2) ) > levelOfSimilarity) {
        return false;
    }
    else {
        return true;
    }
}

std::string replaceChars2Strings(std::string string, const std::string& start, const std::string& end) {

    size_t init_pos = 0;

    while ((init_pos = string.find(start, init_pos)) != std::string::npos) {
        string.replace(init_pos, start.length(), end);
    }
    return string;
}

double FofX(std::string function, std::string value) {

    std::string newfunction = replaceChars2Strings(function, std::string("x"), value);


    if (!parser.compile(newfunction, expression))
    {
        printf("Something went wrong when the expression was being parsed");
    }

    T result = expression.value();

    return result;
}

double DofFofX(std::string function, std::string value) {

    std::string SDplus = replaceChars2Strings(function, std::string("x"), "(" + value + "+" + "0.00001" + ")");
    std::string SDminus = replaceChars2Strings(function, std::string("x"), "(" + value + "-" + "0.00001" + ")");

    if (!parser.compile(SDplus, expression))
    {
        printf("Something went wrong when Dplus was being parsed");
    }
    T Dplus = expression.value();

    if (!parser.compile(SDminus, expression))
    {
        printf("Something went wrong when Dminus was being parsed");
    }
    T Dminus = expression.value();

    return (Dplus - Dminus) / 0.00002;
}

double newton(std::string function, std::string guess) {
    double guess2;
    //std::cout << "guess:" << guess << std::endl;

    //in here () are taken off so that the compiler can calculate the value of guess 2 easier
    guess2 = std::stod(guess.substr(1, guess.size() - 2)) - FofX(function, guess) / DofFofX(function, guess);

    //std::cout << "guess 2:" << guess2 << std::endl;

    //take the () off of guess before we give it away
    if (closeEnough(guess.substr(1, guess.size() - 2), std::to_string(guess2), 0.00001)) {
        std::cout << "final guess  = " << guess2 << std::endl;
        return guess2;
    }
    else {
        return newton(function, "(" + std::to_string(guess2) + ")");
    }
}

int main()
{
    std::string function = "2^x - x^2";
    //remember to put () around guess
    std::string guess = "(-2)";

    double answer = newton(function, guess);
    std::cout << answer << std::endl;

    return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.