求解方程:
#include
<
stdio
.
h
>
#include
<math.
h
>
#include
<
malloc
.
h
>
#include
<stdlib.
h
>
double
Func
(
double
);
int
BisectRoot
(
double
,
double
,
double
,
double
,
double
*,
int
,
int
*);
void
main
()
{
int
i
,
n
,
m
;
double
a
,
b
,
h
,
eps
,*
x
;
n
= 3;
/*
方程根的个数的预估值
*/
x
= (
double
*)
calloc
(
n
,
sizeof
(
double
));
/*
开辟内存空间
*/
if
(
x
==
NULL
)
{
printf
(
"
内存分配失败
/n"
);
exit
(1);
}
a
= -3;
/*
区间起始端点
*/
b
= 7;
/*
区间终止端点
*/
h
= 0.1;
/*
步长
*/
eps
= 1.e-8;
/*
要求达到的精度
*/
BisectRoot
(
a
,
b
,
h
,
eps
,
x
,
n
,&
m
);
/*
调用二分法函数
*/
printf
(
"y=sin(x)
在范围
%2.0f
和
%2.0f
之间的根有
%d
个根
/n"
,
a
,
b
,
m
);
printf
(
"
它们分别是:
/n"
);
for
(
i
= 0;
i
<
n
;
i
++)
printf
(
"x[%d] = %e/n"
,
i
,
x
[
i
]);
free
(
x
);
/*
释放内存空间
*/
}
double
Func
(
double
x
)
{
return
(
sin
(
x
));
}
int
BisectRoot
(
a
,
b
,
h
,
eps
,
x
,
n
,
m
)
double
a
;
/*
实型变量,输入参数,求根区间的起始端点
*/
double
b
;
/*
实型变量,输入参数,求根区间的终止端点
*/
double
h
;
/*
利用逐步扫描法确定根位置时的步长
*/
double
eps
;
/*
实型变量,输入参数,控制精度的参数
*/
double
*
x
;
/*
实型一维数组,输出参数,存放计算得到的数组
*/
int
n
;
/*
输入参数,区间内方程根的个数的预估值
*/
int
*
m
;
/*
输出参数,实际求得的根的个数
*/
{
double
z
,
z0
,
z1
,
y
,
y0
,
y1
;
*
m
= 0;
z
=
a
;
y
=
Func
(
z
);
while
(1)
/*
无限循环,直到遇到
return
或者
break
语句
*/
{
/*
如果逐步扫描到求根区间的右端点或者得到的根的个数达到预估根的个数
*/
if
((
z
>
b
+
h
/2)||(*
m
==
n
))
return
(1);
if
(
fabs
(
y
)<
eps
)
/*
如果当前根
z
对应的函数
f(z)
满足精度要求
*/
{
*
m
+=1;
x
[*
m
-1] =
z
;
/*
将此时的
z
值赋值给
x
数组
*/
z
+=
h
/2;
y
=
Func
(
z
);
continue
;
/*
结束本次循环,即跳过循环体中下面尚未执行
的语句接着进行下一次是否执行循环的判定
*/
}
z1
=
z
+
h
;
/*
逐步扫描中小区间的右端点
*/
y1
=
Func
(
z1
);
/*
小区间右端点对应的函数值
*/
if
(
fabs
(
y1
)<
eps
)
/*
如果右端点恰好满足根的精度要求
*/
{
*
m
+=1;
x
[*
m
-1] =
z1
;
z
=
z1
+
h
/2;
y
=
Func
(
z
);
continue
;
}
if
(
y
*
y1
>0)
/*
如果对应根乘积大于零,说明该区间内没有根
*/
{
y
=
y1
;
z
=
z1
;
continue
;
}
while
(1)
/*
如果本
while
循环执行,说明逐步扫描小区建
z
和
z1
间有根
*/
{
if
(
fabs
(
z1
-
z
)<
eps
)
/*
如果满足精度要求
*/
{
*
m
+=1;
x
[*
m
-1]=(
z1
+
z
)/2;
z
=
z1
+
h
/2;
y
=
Func
(
z
);
break
;
}
z0
= (
z1
+
z
)/2;
/*
二分发求根公式
*/
y0
=
Func
(
z0
);
if
(
fabs
(
y0
)<
eps
)
{
*
m
= *
m
+1;
x
[*
m
-1] =
z0
;
z
=
z0
+
h
/2;
y
=
Func
(
z
);
break
;
}
if
(
y
*
y0
<0)
/*
如果乘积小于零,说明根在
z
和
z0
之间
*/
{
z1
=
z0
;
y1
=
y0
;
}
else
/*
否则根在
z0
和
z1
之间
*/
{
z
=
z0
;
y
=
y0
;
}
}
}
}
牛顿迭代法:
#include
<
stdio
.h>
#include
<math.h>
#include
<stdlib.h>
int
Function
(
double
,
double
*,
double
*);
int
Newton
(
double
*,
double
,
int
);
int
Function
(
x
,
f
,
dy
)
double
x
;
double
*
f
;
double
*
dy
;
{
*
f
=
x
*
x
*(
x
-1)-1;
*
dy
= 3*
x
*
x
-2*
x
;
return
(1);
}
int
Newton
(
x
,
eps
,
l
)
double
*
x
;
double
eps
;
int
l
;
{
double
f
,
dy
,
x1
;
Function
(*
x
,&
f
,&
dy
);
A
:
if
(
fabs
(
dy
) == 0)
{
l
= 0;
return
(0);
}
x1
=*
x
-
f
/
dy
;
Function
(
x1
,&
f
,&
dy
);
if
(
fabs
(
x1
-*
x
)>=
eps
||
fabs
(
f
)>=
eps
)
{
l
-=1;
*
x
=
x1
;
if
(
l
==0)
return
(1);
goto
A
;
}
*
x
=
x1
;
return
1;
}
void
main
()
{
double
x
,
eps
;
int
l
;
eps
=1.e-6;
x
=1.5;
l
=60;
if
(!
Newton
(&
x
,
eps
,
l
))
{
printf
(
"
该函数不可以用牛顿跌代法求根
!/n"
);
}
printf
(
"
利用牛顿跌代法求的的根为:
/n"
);
printf
(
"x=%.10f/n"
,
x
);
}
弦节法:
#include
<
stdio
.
h
>
#include
<math.
h
>
#include
<
malloc
.
h
>
#include
<stdlib.
h
>
double
Func
(
double
);
int
BowRoot
(
double
,
double
,
double
,
double
,
double
*,
int
,
int
*);
void
main
()
{
int
i
,
n
,
m
;
double
a
,
b
,
h
,
eps
,*
x
;
n
= 3;
/*
方程根的个数的预估值
*/
x
= (
double
*)
calloc
(
n
,
sizeof
(
double
));
/*
开辟内存空间
*/
if
(
x
==
NULL
)
{
printf
(
"
内存分配失败
/n"
);
exit
(1);
}
a
= -3;
/*
区间起始端点
*/
b
= 5;
/*
区间终止端点
*/
h
= 1;
/*
步长
*/
eps
= 1.e-8;
/*
要求达到的精度
*/
BowRoot
(
a
,
b
,
h
,
eps
,
x
,
n
,&
m
);
/*
调用二分法函数
*/
printf
(
"
函数
f(x)
在范围
%2.0f
和
%2.0f
之间的根有
%d
个根
/n"
,
a
,
b
,
m
);
printf
(
"
它们分别是:
/n"
);
for
(
i
= 0;
i
<
n
;
i
++)
printf
(
"x[%d] = %e/n"
,
i
,
x
[
i
]);
free
(
x
);
/*
释放内存空间
*/
}
double
Func
(
double
x
)
{
return
(
x
*
x
*
x
-3*
x
*
x
-6*
x
+8);
}
int
BowRoot
(
a
,
b
,
h
,
eps
,
x
,
n
,
m
)
double
a
;
/*
实型变量,输入参数,求根区间的起始端点
*/
double
b
;
/*
实型变量,输入参数,求根区间的终止端点
*/
double
h
;
/*
利用逐步扫描法确定根位置时的步长
*/
double
eps
;
/*
实型变量,输入参数,控制精度的参数
*/
double
*
x
;
/*
实型一维数组,输出参数,存放计算得到的数组
*/
int
n
;
/*
输入参数,区间内方程根的个数的预估值
*/
int
*
m
;
/*
输出参数,实际求得的根的个数
*/
{
double
z
,
z1
,
z2
,
y
,
y1
,
y2
;
*
m
= 0;
z
=
a
;
y
=
Func
(
z
);
while
(1)
/*
无限循环,直到遇到
return
或者
break
语句
*/
{
/*
如果逐步扫描到求根区间的右端点或者得到的根的个数达到预估根的个数
*/
if
((
z
>
b
+
h
/2)||(*
m
==
n
))
return
(1);
if
(
fabs
(
y
)<
eps
)
/*
如果当前根
z
对应的函数
f(z)
满足精度要求
*/
{
*
m
+=1;
x
[*
m
-1] =
z
;
/*
将此时的
z
值赋值给
x
数组
*/
z
+=
h
/2;
y
=
Func
(
z
);
continue
;
/*
结束本次循环,即跳过循环体中下面尚未执行
的语句接着进行下一次是否执行循环的判定
*/
}
z1
=
z
+
h
;
/*
逐步扫描中小区间的右端点
*/
y1
=
Func
(
z1
);
/*
小区间右端点对应的函数值
*/
if
(
fabs
(
y1
)<
eps
)
/*
如果右端点恰好满足根的精度要求
*/
{
*
m
+=1;
x
[*
m
-1] =
z1
;
z
=
z1
+
h
/2;
y
=
Func
(
z
);
continue
;
}
if
(
y
*
y1
>0)
/*
如果对应根乘积大于零,说明该区间内没有根
*/
{
y
=
y1
;
z
=
z1
;
continue
;
}
while
(1)
/*
如果本
while
循环执行,说明逐步扫描小区建
z
和
z1
间有根
*/
{
if
(
fabs
(
z1
-
z
)<
eps
)
/*
如果满足精度要求
*/
{
*
m
+=1;
x
[*
m
-1]=(
z1
+
z
)/2;
z
=
z1
+
h
/2;
y
=
Func
(
z
);
break
;
}
y1
=
Func
(
z1
);
/*
弦截法公式
*/
y
=
Func
(
z
);
z2
=
z1
-(
y1
/(
y1
-
y
))*(
z1
-
z
);
y2
=
Func
(
z2
);
if
(
fabs
(
y2
)<
eps
)
{
*
m
= *
m
+1;
x
[*
m
-1] =
z2
;
z
=
z2
+
h
/2;
y
=
Func
(
z
);
break
;
}
if
(
y
*
y2
<0)
/*
如果乘积小于零,说明根在
z
和
z0
之间
*/
{
z1
=
z2
;
y1
=
y2
;
}
else
/*
否则根在
z0
和
z1
之间
*/
{
z
=
z2
;
y
=
y2
;
}
}
}
}