有你實現你的函數的一個bug。
atan(b*x - 1/2)
術語1/2
做整數除法和計算結果爲0,這可能不是你想要的。通常,在使用雙變量進行算術時使用雙字面值。 pow()
功能確實需要(double, int)
作爲它的一個重載,所以你很好。它也有一個(double, double)
重載,但如果你的指數實際上是一個整數,那麼你不希望這樣。
下面是最簡單的根查找方法的簡單實現 - 平分法(後來我注意到OP使用平分標記,完美)。
#include <iostream>
#include <cmath>
#include <random>
double f(const double x, const double a, const double b, const double c)
{
return sin((a*x/(1.0 + pow(x, 2))) + 1.0) * atan(b*x - 1.0/2.0) + exp(-c*x) * atan(x);
}
double BisectionMethod(
double f(double, double, double, double),
const double a, const double b, const double c,
const std::random_device::result_type entropy)
{
std::mt19937 gen(entropy);
static const auto lower_bound = -1.0;
static const auto upper_bound = 1.0;
std::uniform_real_distribution<> dis(lower_bound, upper_bound);
auto pos_pt = dis(gen);
auto neg_pt = dis(gen);
while (f(pos_pt, a, b, c) < 0.0)
pos_pt = dis(gen);
while (f(neg_pt, a, b, c) > 0.0)
neg_pt = dis(gen);
static const auto about_zero_mag = 1E-8;
for (;;)
{
const auto mid_pt = (pos_pt + neg_pt)/2.0;
const auto f_mid_pt = f(mid_pt, a, b, c);
if (fabs(f_mid_pt) < about_zero_mag)
return mid_pt;
if (f_mid_pt >= 0.0)
pos_pt = mid_pt;
else
neg_pt = mid_pt;
}
}
int main()
{
double a, b, c;
std::random_device rd;
static const auto entropy = rd();
a =10, b = 2.0, c = 0.0;
const auto root1 = BisectionMethod(f, a, b, c, entropy);
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
std::cout << "Found root: (" << root1 << ", " << f(root1, a, b, c) << ")" << std::endl;
a =4.5, b = 2.8, c = 1.0;
const auto root2 = BisectionMethod(f, a, b, c, entropy);
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
std::cout << "Found root: (" << root2 << ", " << f(root2, a, b, c) << ")" << std::endl;
}
Output:
g++ -O3 -std=c++11 -Wall -Wextra -pedantic main.cpp -o root && ./root
a = 10, b = 2, c = 0
Found root: (0.143042, -2.12425e-09)
a = 4.5, b = 2.8, c = 1
Found root: (0.136172, 5.81247e-09)
輸出將每次運行時改變,因爲它使用一個RNG。在視覺上,輸出看起來是正確的
該代碼假定根以-1.0和1.0爲界,在您的情況下爲true。如果你希望它更一般,那麼你需要添加邏輯來處理溢出和檢查nans。如果根不在-1.0和1.0之間,這將永遠循環。儘管如此,它解決了這個問題中的具體問題,並且是更一般化的開始。
另請注意,您的函數有多個根,並且給定的代碼只能找到一個根。
編輯:清理了代碼。作爲BisectionMethod()
的參數添加了entropy
,以便重複性好,如果我們正在談論數值方法,這似乎是可取的。
這是一個相當數學問題,我認爲它屬於另一個網站。但是,並非所有的查找算法都需要一個包含根的區間。所以,要麼嘗試其他算法,要麼挑選一些隨機值,如果公式給出不同的符號,則可以平分。 – Axel 2015-02-07 07:50:49
不會。即使如果它似乎是一個數學問題,我被要求用C++實現。所以,我認爲它屬於這裏。你能幫我結構嗎? – tmgr 2015-02-07 07:51:56
我不同意。你正在尋找一種算法,你根本沒有代碼。你必須先選擇算法,然後從這裏開始尋找:http://math.stackexchange.com/search?q=root+finding。如果您嘗試實現算法並陷入困境,那麼您可以回到這裏,發佈您的代碼並獲得答案。 – Axel 2015-02-07 07:59:30