Search code examples
c++square-rootbisection

Issues with bisection method square root calculation


#include<iostream>
#include<cmath>
#include<iomanip>
using namespace std;
double bisection(double errorVal, double userNum){
    double upper=userNum, lower=0;
    double mid=(lower+upper)/2.0;
    while(!(fabs(mid*mid-userNum)<=errorVal)){
        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 "<<std::setprecision(11)<<bisection(errorVal,userNum)<<". The amount of error is "<<fabs(bisection(errorVal, userNum)-sqrt(userNum))<<"."<<std::endl;
}

This is a prototype program I designed to calculate the square root of a number determined by user input, using bisection method (I know there are better ways such as the Newton-Raphson, CORDIC, but this is the assignment given).

The only problem left is as following:

When input for userNum is a decimal from 0 to 1, the program stalls no matter what the specified precision is, with the notable exception of inputting 0.1, 0.1. This yields the inaccurate result of 0.5, with an error of 0.266227766, which is above the specified error margin of 0.1.

My main questions are, why doesn't it process numbers between 0 and 1?


Solution

  • Square roots of numbers smaller than 1 are larger then the initial number (remember the root function). As userNum is the upper bound of possible results, those roots cannot be computed with your code. As a solution: add

    if( userNum < 1.0 ) {
      upper = 1.0;
    }
    

    in front of the loop.

    To adress the other part of the question: mid actually consists of the true root and an error, mid + \Delta mid. In the fabs-part, you square both. Thus, you actually compare errorVal with (\Delta mid)^2 + 2 mid * \Delta mid, in the end you print for comparison just mid + \Delta mid.