tft每日頭條

 > 生活

 > python中二分法求函數的根

python中二分法求函數的根

生活 更新时间:2025-02-02 22:33:49

平常我們用到的 sqrt 函數求一個數的算術平方根,以前一直好奇究竟是如何計算的。

這篇文章我們就一起來探究一下。

二分法

以前我想到的一種方式是二分法;

假設求根号2的平方根;

假設最開始 min = 1.0,max = 2.0;

則它們的中間值 val = (min max)/2.0;

然後判斷 num = val*val 的結果,

如果 num > 2;則 max = val;

如果 num < 2;則 min = val;

如果 num = 2;則 算術平方根是 val,返回。

當然有人會問,一直不等于能,當然我們可以設置計算次數;

比如執行超過 20 次後就返回,這樣可以避免無線循環下去。

然而這種方法的收斂速度實在太慢,導緻要計算很多次才能達到比較高的精度。

牛頓的方法

網上看到一個說是牛頓的計算方法,假設 f(x) = x^2-2;

在 x^2-2 的曲線上面,先找一個點A(X0,Y0),

過點A做曲線的切線交x軸于B(X1,0);

找到當前點B對應曲線上的點C(X1,Y1);

過點C做曲線的切線交x軸于D(X2,0);

找到當前點D對應曲線上的點E(X2,Y2);

過點E做曲線的切線交x軸于F(X3,0);

.........

按照這個過程一直下去,B D F....将會離曲線與x軸的交點越來越近,即逼近原理。

python中二分法求函數的根(根号2的程序計算方法)1

數學方法

那上面的坐标如何求取呢,對于點A,可以帶入一個方便的坐标(1,-1);

由于CD是切線,點C為切點,則有如下關系:

斜率 y' = BC/BD

而:BD 可以看成是點B的x軸坐标減去點D的x軸坐标,即 BD = X1-X2;

BC 就是C點的y值,即Y1;

上面關系就變成:y' = Y1/(X1-X2)

轉換一下:X1-X2 = Y1/y'

X2 = X1-Y1/y'

轉換成标準的寫法,則有: Xn = Xn-1 - f(Xn-1) / f '(Xn-1)

對于曲線 x^2-2 任意一點的切線可以根據多項式導數方式獲取,即 f '(Xn-1) = 2x;

則有 Xn = Xn-1 - f(Xn-1) / 2x;

将A點(X0,Y0) 由曲線上的點(1,-1)帶入時,

X1 = 1 - (-1/2*1) = 1.5; 此時 Y1 = 1.5^2-2 = 2.25-2 = 0.25;

X2 = 1.5 - 0.25/2*1.5 = 1.416666...667; 此時 Y1 = 0.0069444444...

以此類推

X6 = 1.4142135623730950488016887242096980785696718753772.......

對比網上查找到的根号2前100為如下:

1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850....

可以看到X6寫出來的,僅僅是最後兩位開始不一樣。可見運算次數僅僅6次,精度已經如此高了。

代碼實現

由于C/C 沒找到比較穩定的高精度計算數據類,在此用Python代替了。

實現代碼如下:

from decimal import Decimal from decimal import getcontext work_context = getcontext() work_context.prec = 1000 // 有興趣的可以試試更高精度 num = Decimal(2) // 需要開方的數,可以試試3,5,7,11 。。。 def Xn(x, y): x -= y/(x*Decimal(2)) y = x*x-num return (x,y) x = Decimal(1) y = x*x-num for i in range(0,20): // 計算20次精度已經非常高了 x, y = Xn(x, y) print(x) 第20次結果:(好像精度已經達到1000位了) 1.414213562373095048801688724209698078569671875376948073176679737990732478462 10703885038753432764157273501384623091229702492483605585073721264412149709993 58314132226659275055927557999505011527820605714701095599716059702745345968620 14728517418640889198609552329230484308714321450839762603627995251407989687253 39654633180882964062061525835239505474575028775996172983557522033753185701135 43746034084988471603868999706990048150305440277903164542478230684929369186215 80578463111596668713013015618568987237235288509264861249497715421833420428568 60601468247207714358548741556570696776537202264854470158588016207584749226572 26002085584466521458398893944370926591800311388246468157082630100594858704003 18648034219489727829064104507263688131373985525611732204024509122770022694112 75736272804957381089675040183698683684507257993647290607629969413804756548237 28997180326802474420629269124859052181004459842150591120249441341728531478105 80360337107730918286931471017111168391658172688941975871658215212822951848847

是不是感到震驚,代碼竟然如此短!?

是的,沒有看錯,就這麼一點點。

有興趣的小夥伴可以試試 https://tool.lu/coderunner/ 的在線編譯器;

左上角選擇 Python 然後複制上面的代碼,運行看看結果。(如下圖)

按照同樣的方式,大家是不是可以擴展出3次,5次.....等等的開方計算方式了?

python中二分法求函數的根(根号2的程序計算方法)2

總結

有時候思路正确了,所要做的反而就很少了!

我在心裡十分佩服前人的智慧與偉大!

一起努力,加油!

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2025 - www.tftnews.com All Rights Reserved