当前位置: 首页 > news >正文

平方根求解-趋近法步长保守策略数学推导

平方根求解 — 趋近法步长保守策略数学推导

预计阅读时间:4 分钟

目录

  • 问题描述
  • 保守步长选择推导
  • 实现代码

问题描述

循环退出要求的是函数值误差满足:

∣x2−c∣≤ε|x^2 - c| \leq \varepsilon x2cε

令真实解为 r=cr = \sqrt{c}r=c,设当前估计值为 x=r+Δx = r + \Deltax=r+Δ,其中 Δ\DeltaΔ 是自变量偏差(即 ∣x−r∣=∣Δ∣|x - r| = |\Delta|xr=∣Δ∣)。

则有:

∣x2−c∣=∣(r+Δ)2−r2∣=∣2rΔ+Δ2∣≤2r∣Δ∣+Δ2|x^2 - c| = |(r + \Delta)^2 - r^2| = |2r\Delta + \Delta^2| \leq 2r|\Delta| + \Delta^2 x2c=(r+Δ)2r2=∣2rΔ+Δ22r∣Δ∣+Δ2

如果误差 ≤ε\leq \varepsilonε,并且假设步长很小(即 ∣Δ∣≪1|\Delta| \ll 1∣Δ∣1),可忽略 Δ2\Delta^2Δ2 项,得到近似条件:

2r∣Δ∣≲ε⇒∣Δ∣≲ε2r2r |\Delta| \lesssim \varepsilon \quad \Rightarrow \quad |\Delta| \lesssim \frac{\varepsilon}{2r} 2r∣Δ∣ε∣Δ∣2rε

由于趋近法的最大可能偏差就是步长 δ\deltaδ(因为你只能停在某个 x=k⋅δx = k\cdot\deltax=kδ 上,而真实解可能在两个步长之间),因此为保证 ∣Δ∣<δ≤ε2r|\Delta| < \delta \leq \frac{\varepsilon}{2r}∣Δ∣<δ2rε,必须取:

δ≤ε2c\delta \leq \frac{\varepsilon}{2\sqrt{c}} δ2cε

但这里有个问题:不能在不知道 c\sqrt{c}c 的前提下使用 c\sqrt{c}c —— 这是要计算的目标。

保守步长选择推导

因此,为了构造一个可计算的上界,用一个已知且大于 c\sqrt{c}c 的量来代替分母中的 c\sqrt{c}c。一个简单且安全的(但略松的)选择是:

c≤max⁡(1,c)\sqrt{c} \leq \max(1, c) cmax(1,c)

更合理的做法是直接定义一个无需开方就能计算的上界 U≥cU \geq \sqrt{c}Uc,例如:

  • c≤1c \leq 1c1,则 c≤1\sqrt{c} \leq 1c1
  • c>1c > 1c>1,则 c<c\sqrt{c} < cc<c

因此,可以取

U=max⁡(1,c)U = \max(1, c) U=max(1,c)

于是,保守的步长选择为:

δ=ε2U=ε2⋅max⁡(1,c)\delta = \frac{\varepsilon}{2U} = \frac{\varepsilon}{2\cdot\max(1, c)} δ=2Uε=2max(1,c)ε

上界 UUU 的选择可以根据具体问题更精细地调整(例如可以基于初值估计或区间界来取更紧的上界),这里给出的是一个简单、通用且安全的保守估计。

实现代码

如下为具体实现。

import time
import csv
import math
import mpmathmpmath.mp.dps = 50  # 设置高精度def linear_approximation_sqrt(target, precision=0.0001):"""使用线性逼近法计算平方根。从初始猜测开始,每次增加步长直到足够接近。"""start_time = time.perf_counter_ns()step = precision / (2 * max(1, target)) # 保守策略iterations = 0approx = 0for candidate in range(0, int(target) + 1):if candidate * candidate > target and approx == 0:approx = candidate - 1records = []power = 0max_iterations = 1_000_000_000  # 增加最大迭代限制while abs(approx * approx - target) > precision and iterations < max_iterations:approx += stepiterations += 1if iterations == 2**power:records.append((iterations, approx, time.perf_counter_ns() - start_time))power += 1end_time = time.perf_counter_ns()time_ns = end_time - start_timereturn approx, iterations, time_ns, recordsdef binary_search_sqrt(target, precision=1e-13):"""使用二分查找法计算平方根。不断缩小范围直到达到精度。"""start_time = time.perf_counter_ns()iterations = 0lower_bound = 0.0upper_bound = max(1.0, float(target)) # max(1.0, target) 确保上界至少为 1approx = (lower_bound + upper_bound) / 2.0records = []# 为防止由于数值精度或错误的区间导致无限循环,增加一个保守的停止条件max_iterations = 10_000_000while abs(approx * approx - target) > precision and iterations < max_iterations:records.append((iterations, approx, time.perf_counter_ns() - start_time))if approx * approx < target:lower_bound = approxelse:upper_bound = approxprev_approx = approxapprox = (lower_bound + upper_bound) / 2.0iterations += 1# 如果中点不再改变(浮点原因),退出避免无限循环if approx == prev_approx:breakend_time = time.perf_counter_ns()time_ns = end_time - start_timereturn approx, iterations, time_ns, recordsdef newton_raphson_sqrt(target, precision=1e-13):"""使用牛顿-拉夫逊法计算平方根。使用公式迭代改进近似值。"""start_time = time.perf_counter_ns()approx = target / 2iterations = 0records = []while abs(approx * approx - target) > precision:records.append((iterations, approx, time.perf_counter_ns() - start_time))approx = (approx + target / approx) / 2iterations += 1end_time = time.perf_counter_ns()time_ns = end_time - start_timereturn approx, iterations, time_ns, records# 实验矩阵
experiments = [("1-A", 0.1234, 1e-3),("1-B", 0.1234, 1e-6),("1-C", 0.1234, 1e-8),("2-A", 10.0, 1e-3),("2-B", 10.0, 1e-6),("2-C", 10.0, 1e-8),("3-A", 1234.0, 1e-3),("3-B", 1234.0, 1e-6),("3-C", 1234.0, 1e-8),
]# 方法列表
methods = [("线性逼近法", linear_approximation_sqrt),("二分查找法", binary_search_sqrt),("牛顿-拉夫逊法", newton_raphson_sqrt),
]# 主程序执行
with open("平方根实验结果.txt", "w", encoding="utf-8") as f, open("平方根实验结果.csv", "w", newline='', encoding="utf-8") as csv_f, open("records.csv", "w", newline='', encoding="utf-8") as rec_csv:writer = csv.writer(csv_f)rec_writer = csv.writer(rec_csv)writer.writerow(["实验ID", "方法", "近似值", "迭代次数", "运行时间(ns)", "记录点数", "初始误差", "最终误差", "平均误差变化"])rec_writer.writerow(["实验ID", "方法", "迭代次数", "近似值", "误差", "相对时间(ns)"])for exp_id, target, precision in experiments:print(f"Running experiment {exp_id} with target {target}, precision {precision}")true_sqrt = mpmath.sqrt(target)f.write(f"\n实验 {exp_id} (Target={target}, Precision={precision}):\n")for method_name, method_func in methods:print(f"  Running {method_name}...")approx, iter_count, time_ns, records = method_func(target, precision)print(f"  Finished {method_name}: approx {approx:.6f}, iterations {iter_count}, time {time_ns} ns")final_error = abs(float(approx) - float(true_sqrt))f.write(f"  {method_name}: 近似值={approx:.13f}, 迭代次数={iter_count}, 运行时间={time_ns} ns, 最终误差={final_error:.2e}\n")if records:for iter_num, app, rel_time in records:err = abs(float(app) - float(true_sqrt))rec_writer.writerow([exp_id, method_name, iter_num, f"{app:.13f}", f"{err:.2e}", rel_time])f.write(f"    记录已写入 records.csv\n")initial_error = abs(float(records[0][1]) - float(true_sqrt))f.write(f"    记录点数: {len(records)}, 初始误差: {initial_error:.2e}, 最终误差: {final_error:.2e}\n")if len(records) > 1:error_changes = [abs(float(records[i][1]) - float(true_sqrt)) - abs(float(records[i-1][1]) - float(true_sqrt)) for i in range(1, len(records))]avg_error_change = sum(error_changes) / len(error_changes)f.write(f"    平均误差变化: {avg_error_change:.2e}\n")else:avg_error_change = 0writer.writerow([exp_id, method_name, f"{approx:.13f}", iter_count, time_ns, len(records), f"{initial_error:.2e}", f"{final_error:.2e}", f"{avg_error_change:.2e}"])else:f.write("    无记录\n")writer.writerow([exp_id, method_name, f"{approx:.13f}", iter_count, time_ns, 0, "", "", ""])print("结果已写入平方根实验结果.txt、平方根实验结果.csv 和 records.csv")       
http://www.dtcms.com/a/528739.html

相关文章:

  • JSP 文件上传
  • 基于深度生成模型的单细胞多时间点数据分析与药物发现
  • FreeRTOS信号量实战:停车场管理
  • 做网站一般不选用的图片格式万能浏览器手机版下载安装
  • Federated Learning-Empowered AI-Generated Content in Wireless Networks
  • 网站建设外包还是自己做乐清网站建设公司
  • 计算机网络自顶向下方法4——详解协议层次及其服务模型
  • 【开题答辩全过程】以 暴肌兔健康饮食推荐系统的设计与实现为例,包含答辩的问题和答案
  • 网站找不到首页网站开发分前台后台
  • 网站微信支付怎么做深圳品牌做网站公司哪家好
  • jEasyUI 创建异步树形菜单
  • fabric.js 中originX originY center设置问题
  • java开发手册与规范
  • 展示网站开发 大概多少钱wordpress+4.2.4中文
  • 深圳建设局官网站对网站建设需求
  • linux:查看某个文件下开启的进程占用的是哪个端口?
  • 【开题答辩过程】以《基于微信小程序的街道水电费缴纳系统》为例,不会开题答辩的可以进来看看
  • (数据结构)栈和队列
  • 体育西网站开发方案成都和奇乐网站建设公司怎么样
  • 网站管理后台 模板河南省建设厅网站总经济师
  • 网站建设难学吗广西建设厅官网站
  • Linux内核RDMA通信管理器ConfigFS配置接口深度解析
  • R语言模型分析(一)
  • gitee简易的命令入门教程
  • 永康建设局网站电话佛山建网站
  • Profinet 转 TCP/IP 协议转换网关:打破 PLC 与打标卡协议壁垒的工业通讯利器
  • 做网站花了2万多做网站的专业公司
  • OceanBase常见Hint使用
  • LeetCode算法日记 - Day 83: 乘积最大的子数组
  • 站长之家的作用什么是优化资源配置