Search code examples
c++codeblockssquare-rootbisection

Problems finding a number's square root with bisection method


#include<iostream>
#include<cmath>
using namespace std;
double bisection(double errorVal, double userNum){
    double upper=userNum, lower=0;
    double mid=(lower+upper)/2.0;;
    while(mid*mid!=userNum){
        double mid=(lower+upper)/2.0;
        if(mid*mid>userNum){
            upper=mid;
        } else {
            lower=mid;
        }
    }
    return mid;
}

int main(){
    double errorVal=0, userNum=0;
    std::cout<<"Please enter a number (larger than 0) to calculate its square root, and the desired margin of error."<<std::endl;
    std::cin>>userNum>>errorVal;
    bisection(errorVal,userNum);
    std::cout<<"The calculated result is "<<bisection(errorVal,userNum)<<". The error is "<<abs(bisection(errorVal,userNum)-sqrt(userNum))<<"."<<std::endl;
}

This is a program I have written to find the square root of any number inputted via the bisection method. I must be doing something wrong here because I am not getting any output once I enter the two input parameters, the process just gets stuck there.

I would also like to know how to properly implement errorVal, as to specify the margin of error allowed. Thanks.


Solution

  • The error value is used to fix any rounding inaccuracies which occur while doing floating point operations.

    The following statement would seldom be true, therefor your loop is likely to continue for a long time.

    while(mid*mid==userNum)
    

    The usual way to compare two floating points after calculation is

    fabs(x1-x2) < e //where, fabs retrieves the absolute value, 
                    //x1,2 are the numbers to compare 
                    //and e is the epsilon chosen. 
    

    So, fixing the error value, or commonly referred to as epsilon, would fix the loop as well.

    double bisection(double errorVal, double userNum){
        double upper=userNum, lower=0;
        double mid=(lower+upper)/2.0;
    
         //error val added
         //** fabs(mid*mid - userNum) < errorVal is true if the numers are "equal"
         //** and you want to run the loop as long as the are NOT "equal" 
         while(!(fabs(mid*mid - userNum) < errorVal)){
    
            mid=(lower+upper)/2.0;
            if(mid*mid>userNum){
               upper=mid;
            } else {
                lower=mid;
            }
        }
        return mid;
    }
    

    See: http://www.cplusplus.com/reference/cmath/fabs/

    https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/