二分法解方程近似解
基礎知識:
如果要求已知函數 f(x) = 0 的根 (x 的解),那麼先要找出一個區間 [a, b],使得f(a)與f(b)異號。
根據介值定理,這個區間內一定包含着方程式的根。
求該區間的中點m=(a+b)/2,並找出 f(m) 的值。
若 f(m) 與 f(a) 正負號相同,則取 [m, b] 爲新的區間, 否則取 [a, m]。
重複第3步和第4步,直到得到理想的精確度爲止。
第一次遇到的相關題目:
Solve the equation:
p ∗ e −x + q ∗ sin(x) + r ∗ cos(x) + s ∗ tan(x) + t ∗ x 2 + u = 0 where 0 ≤ x ≤ 1.
Input
Input consists of multiple test cases and terminated by an EOF. Each test case consists of 6 integers in a single line: p, q, r, s, t and u (where 0 ≤ p, r ≤ 20 and −20 ≤ q, s, t ≤ 0). There will be maximum 2100 lines in the input file.
Output
For each set of input, there should be a line containing the value of x, correct up to 4 decimal places, or the string ‘No solution’, whichever is applicable.
Sample Input
0 0 0 0 -2 1
1 0 0 0 -1 2
1 -1 1 -1 -1 1
Sample Output
0.7071
No solution
0.7554
題意:
用程序解出方程的根。其中,輸入是p q r s t u 6個量。
大概思路:
我想到的是迭代法和二分法來求近似解。因爲,題目一開始就給出了x的取值範圍,這就是和介值定理有相關的地方。
AC代碼:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int p, q, r, s, t, u;/*用全局變量定義輸入變量,可免去重複定義函數的麻煩*/
double ha(double x);
double haha(double m, double n);
int main()
{
//freopen("a.txt", "r", stdin);
while(scanf("%d%d%d%d%d%d", &p, &q, &r, &s, &t, &u) != EOF)
{
double a, b, x, huh1, huh2;
a = 0;
huh1 = ha(a);
b = 1;
huh2 = ha(b);
if(abs(huh1) <= 0.000001)
printf("0.0000\n");
else if(abs(huh2) <= 0.000001)
printf("1.0000\n");
else if(huh1*huh2 > 0)
printf("No solution\n");
else
{
x = haha(a, b);
printf("%.4f\n", x);
}
}
return 0;
}
double ha(double x)
{
double y;
y = p*exp(-x) + q*sin(x) + r*cos(x) + s*tan(x) + t*pow(x,2) + u;/*定義函數*/
return y;
}
double haha(double m, double n)
{
double x, y, y1, y2, a, b;
a = m;
b = n;
while(1)
{
x = (a+b)/2;
y = ha(x);
if(fabs(y) < 0.000001)
return x;
y1 = ha(a);
y2 = ha(b);
if(y*y1 < 0) b = x;//若最左端點的因變量和中值異號則使b=x
if(y*y2 < 0) a = x;//同理使a=x
/********************************************************************
其實上面的改變範圍有些麻煩可以用下面的方法:
if(y < 0) b = x; else a = x;
只要判定中值符號即可
********************************************************************/
}
}