二分法解方程近似解
基础知识:
如果要求已知函数 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; 只要判定中值符号即可 ********************************************************************/ } }