题目描述
计算一个浮点数的立方根,不使用库函数。
保留一位小数。
数据范围: ∣ v a l ∣ ≤ 20 |val| \le 20 ∣val∣≤20
输入描述
待求解参数,为double类型(一个实数)
输出描述
输出参数的立方根。保留一位小数。
代码&解释
牛顿迭代法
牛顿迭代法与泰勒定理相关,由泰勒定理,函数
f
(
x
)
f(x)
f(x)在
x
0
x_0
x0附近的值可近似为
f
(
x
)
=
f
(
x
0
)
+
f
′
(
x
0
)
(
x
−
x
0
)
f(x)=f(x_0)+f'(x_0)(x-x_0)
f(x)=f(x0)+f′(x0)(x−x0),由此可得若
f
(
x
)
=
0
f(x)=0
f(x)=0则有
x
=
x
0
−
f
(
x
0
)
/
f
′
(
x
0
)
x=x_0-f(x_0)/f'(x_0)
x=x0−f(x0)/f′(x0)
以该式作为迭代公式,设置预期的精度则可以得到零点的近似值,即立方根的近似值
while True:
try:
n=float(input())
e=0.0001 #精度
x=n #初值3为输入值
while abs(x*x*x-n)>e:
x=x-(x*x*x-n)/(3*x*x)
print('%.1f'%(x))
except:
break
零点存在定理&区间套定理
这个解法的基于的原理是数学分析里连续函数的零点存在定理,以及区间套定理。区间套定理的证明过程其实就是代码实现求解立方根的一个过程,而零点存在定理则是帮助确定我们做区间分割时的第一个区间。
先附上两个定理。来源:华师版本的数学分析教材
零点存在定理
若函数 f f f在闭区间 [ a , b ] [a,b] [a,b]上连续且 f ( a ) f(a) f(a)与 f ( b ) f(b) f(b)异号,则至少存在一点 x 0 ∈ ( a , b ) x_0 \in (a,b) x0∈(a,b),使得 f ( x 0 ) = 0 f(x_0)=0 f(x0)=0
区间套定理
若 { [ a n , b n ] } \{[a_n,b_n]\} {[an,bn]}是一个区间套,则在实数系中存在唯一的一点 ξ \xi ξ,使得 ξ ∈ [ a n , b n ] \xi \in[a_n,b_n] ξ∈[an,bn], n = 1 , 2 , . . . n=1,2,... n=1,2,...,即 a n ≤ ξ ≤ b n a_n\leq\xi\leq b_n an≤ξ≤bn.
代码实现
由零点存在定理,可以先确定一个存在零点的区间。再由区间套定理,当这个区间足够小的时候,这个唯一的值
ξ
\xi
ξ就可以作为零点的近似值。
因此我们仿照区间套定理的证明,对区间套的第一个区间对半分,选取零点所在的那一半区间作为第二个区间,以此类推。当区间长度小于我们所设置的精度时,即得到所求。
# f(x)=x**3-n
while True:
try:
n=float(input())
e=0.0001 #精度
x=n #初值3为输入值
# 确定区间
if abs(n)>1:
# f(0)f(n)<0
a,b=0,n
elif 0<n<1:
# f(0)f(1)<0
a,b=0,1
elif -1<n<0:
# f(-1)f(0)<0
a,b=-1,0
if abs(n)==1 or n==0:
print('%.1f'%(n))
else:
ans=(a+b)/2
while abs(ans**3-n)>=e:
if (ans**3-n)*(b**3-n)<0:
a=ans
else:
b=ans
ans=(a+b)/2
print('%.1f'%(ans))
except:
break