二分法丢失了精度

时间:2012-10-08 18:16:06

标签: numerical-methods double-precision bisection

我已经离开这个非常好的论坛一段时间了。 我正在学习数值分析课程,我被要求编写二分法,这是我的代码

/*
 * Bisection.cpp
 *
 *  Created on: 08/10/2012
 *  Author: BRabbit27
 *  École Polytechnique Fédérale de Lausanne - M.Sc. CSE
 */

#include <cmath>
#include <iostream>

using namespace std;

double functionA(double x) {
    return sin(2.0 * x) - 1.0 + x;
}

double functionB(double x) {
    return 2.0 * x / (1.0 + x / 1.5);
}

double bisectionMethod(double (*function)(double), double a, double b, double tolerance) {
    double x;
    double f;
    double error = tolerance + 1;
    int step = 0;
    double fa = (*function)(a);
    double fb = (*function)(b);
    //Check the conditions of a root in the given interval
    if (a < b) {
        if (fa * fb < 0) {
            while (error > tolerance) {
                step++;

                x = (a + b) / 2.0;
                f = (*function)(x);

                if (f == 0) {
                    cout << "Root found in x = " << x;
                    return x;
                } else if (f * fa > 0) {
                    a = x;
                } else if (f * fa < 0) {
                    b = x;
                }
                error = (b - a) / pow(2.0, (double) step + 1);
            }
            cout << "Root found in x = " << x;
            return x;
        } else {
            cout << "There not exist a root in that interval." << endl;
            return -1;
        }
    } else {
        cout << "Mandatory \"a < b\", verify." << endl;
        return -1;
    }
}

int main(int argc, char *argv[]){
    bisectionMethod(functionA, -3.0, 3.0, 10.0e-7);
}

我遇到的唯一问题是当 x = 0.354492 时发现根,并且真正的根位于 x = 1/3 所以实际上要么我有坏事具有双精度或我的公差。我不知道如何改进此代码以获得更好的结果。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

The real root is not x = 1/3!这是3.52288

  

sin(2.0 * x) - 1.0 + x = 0

     

sin(2.0 * x)= 1 - x

     

1 - 1/3 = 2/3

     

罪(2/3)!= 2/3


你对宽容的定义让我感到奇怪。宽容应该是你要接受的x范围,对吧?嗯,这很简单:b - a > tolerance

double bisectionMethod(double (*function)(double), double a, double b, double tolerance) {
    if (a > b) {
        cout << "Mandatory \"a < b\", verify." << endl;
        return -1;
    }
    double fa = function(a);
    double fb = function(b);
    if (fa * fb > 0) {
        cout << "No change of sign - bijection not possible" << endl;
        return -1;
    }

    do {    
        double x = (a + b) / 2.0;
        double f = (*function)(x);

        if (f * fa > 0) {
            a = x;
        } else {
            b = x;
        }
    } while (b - a > tolerance);

    cout << "Root found in x = " << x;
    return x;
}