【腾讯笔试】一元三次方程求根 —— 万能的二分

一元三次方程,若已知必有一正实根,求根(若有多个根只需求任意一个)
在这里插入图片描述

二分解法

数值法,用二分去逼近解的区间,高中数学流程图那章有类似的题。
对于区间[a,b],若满足下式,则区间内必有一根。
在这里插入图片描述
对于必有一根的区间[a,b],可以如下所示用二分去缩小区间。停止条件为解的误差(即区间长度)小于某值或者解代入函数十分接近0。
在这里插入图片描述

核心代码如下:

ans = 0
while (r-l) > 10**(-7):
    mid = (l+r)/2
    fmid = f(mid, a, b, c)
    if fmid == 0:
        ans = mid
        break
    elif fmid*fl < 0:
        r = mid
    else:
        l = mid
ans = l if ans == 0 else ans

最初的右边界怎么找

如果系数a,b,c有一定范围,那就可以大致求一个右边界出来,例如若a,b,c都为正整数,则右边界为c。对于更一般的情况,可以用逆向二分去找到一个初始的右边界。
即,若不满足条件则 r <- r*2,直到满足边界值异号。

l, r =0, 1
fl = -c
fr = f(r, a, b, c)

while fr*fl > 0:
    r *= 2
    fr = f(r, a, b, c)

完整代码

n = int(input())
def f(x, a, b, c):
    return x**3+a*(x**2)+b*x-c
    
for _ in range(n):
    ans = 0
    a, b, c = map(int, input().split())
    l, r = 0, 1
    fl = -c
    fr = f(r, a, b, c)
    
    while fr*fl > 0:
        r *= 2
        fr = f(r, a, b, c)
    if fr == 0:
        ans = r
        print(round(float(ans), 8))
        continue
    
    while (r-l) > 10**(-7):
        mid = (l+r)/2
        fmid = f(mid, a, b, c)
        if fmid == 0:
            ans = mid
            break
        elif fmid*fl < 0:
            r = mid
        else:
            l = mid
    ans = l if ans == 0 else ans
    print(round(float(ans), 8))    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值