Swift 二分法求函數的近似解

在實際開發中會遇到一些工程問題,需要求解復雜函數方程的問題。使用傳統的數學方法比較難以處理。本文將使用二分法不斷獲取一個函數的近似解

二分法:其基本思想是利用函數在某個區間內的連續性,通過不斷縮小區間范圍來逼近方程的解。

算法前置要求

在使用二分法求解函數值近似解之前,需要滿足以下幾個前置條件:

  • 函數連續性
    為了確保在區間內存在一個近似解,函數 f(x)必須是連續的。否則,可能會因為函數不連續導致二分法無法收斂到正確的解。

  • 單調性判斷
    在應用時需要確保函數在所選區間內為單調函數。二分法在求解過程中的邊界更新依賴于函數的單調性判斷。通過比較區間端點的函數值來決定是否為單調遞增或者遞減。 如果函數整體不是單調的,但是在某區間內單調遞增或者單調遞減,那么也可以求區間內的結果。

  • 初始區間覆蓋目標值
    要求區間 [lowerBound,upperBound]的值域內必須包含目標值 target 的對應函數值。

以函數示例 f(x) = x^3 - 4x^2 + 6x - 24,同時滿足3個條件:? ?連續性 && 單調性 && 起始位置覆蓋區間值

算法思路

整個算法的核心步驟如下:

  1. 區間初始化
    首先,在已知的區間 [lowerBound,upperBound]內,假設函數 f(x)在此區間內是單調連續的,并且存在滿足條件的解。

  2. 迭代過程

    • 計算當前區間的中點 mid。
    • 判斷當前區間長度是否小于 x 方向的容忍誤差 toleranceX,如果滿足條件,則停止迭代。
    • 同時,計算 f(mid)?與目標值 target 的差距,如果差距小于函數值的容忍誤差 toleranceResult,則認為找到近似解。
    • 判斷函數的單調性
      • 單調遞增函數:如果 f(mid)小于 target,則將lowerBound更新為 mid;如果f(mid)大于 target,?則將upperBound更新為 mid。
      • 單調遞減函:如果 f(mid)大于 target,則將lowerBound更新為 mid;如果f(mid)小于 target,?則將upperBound更新為 mid。
  3. 結果判斷
    當迭代結束后,比較區間兩端點以及中點的函數值誤差,選擇誤差最小的點作為最終結果返回。

代碼實現與詳細注釋

下面是 Swift 語言實現的完整代碼,函數 f(x) 可以替換成其他單調連續函數:


import Foundationclass YCCloseToResult: NSObject {// 定義函數 f(x) = x^3 - 4x^2 + 6x - 24static func f(x: Double) -> Double {return pow(x, 3) - 4 * pow(x, 2) + 6 * x - 24}// 二分法:在區間 [lowerBound, upperBound] 內尋找使得 f(x) 接近 target 的 x 值/// - Parameters:///   - target: 目標函數值,即希望 f(x) 接近的數值。///   - lowerBound: 搜索區間的下界,表示在該值以上開始尋找滿足條件的 x 值。///   - upperBound: 搜索區間的上界,表示在該值以下開始尋找滿足條件的 x 值。///   - toleranceX: x 方向的容忍誤差。當上下界之差小于此值時,認為 x 的精度已經滿足要求,從而停止迭代。///   - toleranceResult: 函數值的容忍誤差。當 f(x) 與 target 的差值小于此值時,認為已經找到了足夠精確的近似解,從而停止迭代。/// - Returns: 返回使 f(x) 接近 target 的 x 值;如果在給定區間內沒有找到合適的解,則返回 nil。static func bisectionMethod(target: Double, lowerBound: Double, upperBound: Double, toleranceX: Double = 0.01, toleranceResult: Double = 0.01) -> Double? {var lower = lowerBound   // 區間下界var upper = upperBound   // 區間上界var mid: Double = 0var loopCount = 0        // 記錄循環次數var fMid: Double = 0     // 中點對應的 f(x) 值var fUpper: Double = self.f(x: upper)   // 上界對應的 f(x) 值var fLower: Double = self.f(x: lower)   // 下界對應的 f(x) 值if target > max(fLower, fUpper) || target < min(fLower, fUpper) {print("目標值不在給定區間內")return nil}// 開始迭代while true {loopCount += 1mid = (lower + upper) / 2  // 計算中點// 如果區間長度小于 x 的容忍誤差,則認為 x 精度達到要求if (upper - lower) <= toleranceX {print("x誤差達到精度要求")break}// 計算當前下界、中點和上界的函數值fMid = self.f(x: mid)fUpper = self.f(x: upper)fLower = self.f(x: lower)print("循環次數: \(loopCount); f(\(lower))=\(fLower), f(\(mid))=\(fMid), f(\(upper))=\(fUpper)")// 如果中點對應的函數值與目標值之間的誤差滿足要求,則退出循環if abs(fMid - target) < toleranceResult {print("結果達到精度要求")break} else {// 根據函數單調性判斷:這里假設函數在區間內單調if fLower < fUpper {  // 單調遞增函數// 如果中點的函數值小于目標值,則更新下界if fMid < target {lower = mid} else { // 否則更新上界upper = mid}} else {  // 單調遞減函數if fMid < target {upper = mid} else {lower = mid}}}}print("總循環次數: \(loopCount)")// 在 lower, mid, upper 中選擇哪個點的函數值最接近 targetlet absLower = abs(fLower - target)let absMid = abs(fMid - target)let absUpper = abs(fUpper - target)var result: Double = 0if absLower < absMid, absLower < absUpper {result = lower} else if absMid < absLower, absMid < absUpper {result = mid} else {result = upper}return result}
}// 測試函數
extension YCCloseToResult {// 示例入口函數,用于測試二分法查找static func test() {// 目標函數值let target = 10.13// x 的容忍誤差:當上下界的差值小于這個值時停止迭代let toleranceX: Double = 0.01// 函數值的容忍誤差:當 f(x) 與 target 的差值小于這個值時認為已找到近似解let toleranceResult: Double = 0.001// 調用二分法函數,尋找使 f(x) 接近 target 的 x 值if let result = self.bisectionMethod(target: target, lowerBound: -100, upperBound: 100, toleranceX: toleranceX, toleranceResult: toleranceResult) {print("\(target) 的近似解是 \(result)")// 分別打印 result 左側、處于和右側附近的 x 對應的函數信息self.showInfo(result: result-toleranceX, target: target)self.showInfo(result: result, target: target)self.showInfo(result: result+toleranceX, target: target)} else {print("在給定的范圍內沒有找到解。")}}// 打印函數 f(x) 的值以及與目標值 target 的誤差static func showInfo(result: Double, target: Double) {let fRes = self.f(x: result)let absRes = abs(fRes - target)print("f(\(result)) 的值是 \(fRes), 誤差為 \(absRes)")}
}

運行結果: 通過不斷的二分接近,最終求得結果

10.13 的近似解是 4.401206970214844

f(4.401206970214844) 的值是 10.178870703912295, 和目標差值為 0.048870703912294644

二分查找的時間復雜度為O(logN),效率還不錯。

使用Python畫的函數圖。

import matplotlib.pyplot as plt
import numpy as np# 定義函數 f(x)
def f(x):return x**3 - 4*x**2 + 6*x - 24# 生成 x 值
x = np.linspace(-10000, 10000, 10)
# 計算對應的 y 值
y = f(x)# 創建圖形
plt.figure(figsize=(10, 6))
plt.plot(x, y, label=r'$f(x) = x^3 - 4x^2 + 6x - 24$')# 添加標題和標簽
plt.title('Plot of $f(x) = x^3 - 4x^2 + 6x - 24$')
plt.xlabel('x')
plt.ylabel('f(x)')# 添加網格
plt.grid(True)# 顯示圖例
plt.legend()# 顯示圖形
plt.show()

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/73351.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/73351.shtml
英文地址,請注明出處:http://en.pswp.cn/web/73351.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

stanley 路徑跟蹤控制算法

文章目錄 寫在前面的話算法思路核心代碼1 路徑發布2 獲取車子當前位置3 預瞄路徑點4 計算航向誤差5 計算橫向誤差 完整控制代碼演示視頻 寫在前面的話 軌跡跟蹤 Trajectory Tracking 和 路徑跟蹤 Path Following 是機器人控制和自動駕駛領域中的兩個核心概念&#xff0c;盡管它…

Qt中通過QLabel實時顯示圖像

Qt中的QLabel控件用于顯示文本或圖像&#xff0c;不提供用戶交互功能。以下測試代碼用于從內置攝像頭獲取圖像并實時顯示&#xff1a; Widgets_Test.h&#xff1a; class Widgets_Test : public QMainWindow {Q_OBJECTpublic:Widgets_Test(QWidget *parent nullptr);~Widgets…

在STM32F7上實現CAN總線收發隊列

下面我將提供一個完整的STM32F7 CAN總線通信實現方案&#xff0c;包含中斷驅動的收發隊列管理。 1. CAN總線配置與隊列定義 can_bus.h #ifndef __CAN_BUS_H #define __CAN_BUS_H#include "stm32f7xx_hal.h" #include "queue.h"// CAN消息結構體 typedef …

【例3.5】位數問題(信息學奧賽一本通-1313)

【題目描述】 在所有的N位數中&#xff0c;有多少個數中有偶數個數字3?由于結果可能很大&#xff0c;你只需要輸出這個答案對12345取余的值。 【輸入】 讀入一個數N(N≤1000)。 【輸出】 輸出有多少個數中有偶數個數字3。 【輸入樣例】 2 【輸出樣例】 73 【題解代碼】 #incl…

pyQt學習筆記——Qt資源文件(.qrc)的創建與使用

Qt資源文件&#xff08;.qrc&#xff09;的創建與使用 1. 選擇打開資源2. 創建新資源3. 添加資源文件夾4. 選擇要加載的圖片文件5. 編譯resource.qrc文件6. 替換PySlide6為PyQt57. 其他說明 1. 選擇打開資源 在Qt項目中&#xff0c;可以通過windowIcon點擊選擇打開資源。 2. 創…

光電效應及普朗克常數的測定數據處理 Python實現

內容僅供參考&#xff0c;如有錯誤&#xff0c;歡迎指正&#xff0c;如有疑問&#xff0c;歡迎交流。 因為我不會Excel所以只能用Python來處理 祝大家早日擺脫物理實驗的苦海 用到的一些方法 PCHIP &#xff08;分段三次埃爾米特插值多項式&#xff09; 因為實驗時記錄的數…

2025最新3個wordpress好用的主題

紅色大氣的wordpress企業主題&#xff0c;適合服務行業的公司搭建企業官方網站使用。是一款專為中小企業和個人開發者設計的WordPress主題&#xff0c;旨在提供專業的網站構建解決方案。 通過此WordPress主題&#xff0c;用戶可以輕松創建和維護一個專業的企業網站&#xff0c…

OLLVM 增加 CC++ 字符串加密功能

版權歸作者所有&#xff0c;如有轉發&#xff0c;請注明文章出處&#xff1a;https://cyrus-studio.github.io/blog/ 前言 當我們如果沒有對字符串進行加密&#xff0c;使用 IDA 反匯編一下 so 可以看到 C 代碼中的字符串就直接暴露了。 字符串加密原理 sobf.c #include <…

桑福德·韋爾策劃美國捷運公司收購南美銀行案例分析

桑福德韋爾(Sanford I. Weill)在1981年策劃美國捷運公司(American Express)以5.5億美元收購南美貿易發展銀行所屬外國銀行機構的案例中,展現了其作為戰略家與執行者的雙重能力。這一交易的流程和韋爾的具體行為可從以下六個關鍵環節解析: 一、戰略定位與目標篩選 戰略目標…

人工智能與區塊鏈融合:開啟數字信任新時代

引言 在當今數字化飛速發展的時代&#xff0c;人工智能&#xff08;AI&#xff09;與區塊鏈技術正以前所未有的速度改變著我們的生活和工作方式。AI以其強大的數據處理和智能決策能力&#xff0c;為各行業帶來了效率的飛躍&#xff1b;而區塊鏈則以其去中心化、不可篡改的特性…

自動化逆向框架使用(Objection+Radare2)

1. 工具鏈架構與核心優勢 1.1 動靜結合逆向體系 graph LR A[動態分析] -->|Objection實時Hook| B[關鍵點定位] B --> C[行為數據捕獲] D[靜態分析] -->|Radare2深度解析| E[控制流重建] E --> F[漏洞模式識別] B --> F C --> F 組合優勢對比&…

流式ETL配置指南:從MySQL到Elasticsearch的實時數據同步

流式ETL配置指南&#xff1a;從MySQL到Elasticsearch的實時數據同步 場景介紹 假設您運營一個電商平臺&#xff0c;需要將MySQL數據庫中的訂單、用戶和產品信息實時同步到Elasticsearch&#xff0c;以支持實時搜索、分析和儀表盤展示。傳統的批處理ETL無法滿足實時性要求&…

Docker-Volume數據卷詳講

Docker數據卷-Volume 一&#xff1a;Volume是什么&#xff0c;用來做什么的 當刪除docker容器時&#xff0c;容器內部的文件就會跟隨容器所銷毀&#xff0c;在生產環境中我們需要將數據持久化保存&#xff0c;就催生了將容器內部的數據保存在宿主機的需求&#xff0c;volume …

單片機和微控制器知識匯總——《器件手冊--單片機、數字信號處理器和可編程邏輯器件》

目錄 四、單片機和微控制器 4.1 單片機(MCU/MPU/SOC) 一、定義 二、主要特點 三、工作原理 四、主要類型 五、應用領域 六、選型與設計注意事項 七、發展趨勢 4.2 數字信號處理器(DSP/DSC) ?編輯?編輯 一、定義 二、工作原理 三、結構特點 四、應用領域 五、選型與設計注…

macOS 安裝 Miniconda

macOS 安裝 Miniconda 1. Quickstart install instructions2. 執行3. shell 上初始化 conda4. 關閉 終端登錄用戶名前的 base參考 1. Quickstart install instructions mkdir -p ~/miniconda3 curl https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh -o…

高數下---8.1平面與直線

目錄 平面的確定 直線的確定 若要求某一直線或平面就根據要素來求。 例題 平面中的特殊情況 平面中的解題思路 直線的解題思路 平面的確定 兩要素 一 一點 二 傾斜角 即法向量 點法式 可化為一般式 Ax By Cz D 0; (A,B,C) 即法向量&#xff1b; 改變D 即…

CMS遷移中SEO優化整合步驟詳解

內容概要 在CMS遷移過程中&#xff0c;系統化的規劃與執行是保障SEO排名穩定性的核心。首先需明確遷移流程的關鍵階段&#xff0c;包括數據備份、URL適配、元數據同步及安全配置等環節。其中&#xff0c;數據備份不僅需覆蓋原始數據庫與靜態資源&#xff0c;還需驗證備份文件的…

存儲過程、存儲函數與觸發器詳解(MySQL 案例)

存儲過程、存儲函數與觸發器詳解&#xff08;MySQL 案例&#xff09; 一、存儲過程&#xff08;Stored Procedure&#xff09; 定義 存儲過程是預先編譯好并存儲在數據庫中的一段 SQL 代碼集合&#xff0c;可以接收參數、執行邏輯操作&#xff08;如條件判斷、循環&#xff09;…

Python:進程間的通信,進程的操作隊列

進程間的隊列&#xff1a; 隊列的基本操作&#xff1a; 入隊&#xff1a;將數據放到隊列尾部 出隊&#xff1a;從隊列的頭部取出一個元素 maxsize&#xff1a;隊列中能存放數據個數的上限(整數)&#xff0c;一旦達到上限插入會導致阻塞&#xff0c;直到隊列中的數據被消費掉 …

【C++初階】--- 類與對象(中)

1.類的默認成員函數 默認成員函數就是??沒有顯式實現&#xff0c;編譯器會?動?成的成員函數稱為默認成員函數。?個類&#xff0c;我們不寫的情況下編譯器會默認?成以下6個默認成員函數&#xff0c;我們主要需要掌握前4個&#xff0c;后兩個了解以下即可&#xff0c;默認…