【学习笔记】平方根计算教程
2026-05-12 22:33:46
发布于:浙江
最近有些人私聊我说标准库的sqrt函数精度不够,想让我出一期教程,让精度提升至long double、__float128,……
首先,牛顿送代法都听说过吧,他的公式只需要算一阶导数,这里公式推导过程就不细讲了,直接上公式:x_new=(x^2 +n)/2x(标准公式推导出来是:x_new=x-(x^2 -n)/2x,前面的是简化过后的),如果对效率没有太大需求的话(如只是算个几十位,用来炫技等)可以直接用了。
代码示范:
#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("Ofast", "unroll-loops", "no-stack-protector", "fast-math")
#pragma GCC target("avx2", "avx512f", "avx512vl", "fma", "bmi2", "popcnt")
#pragma GCC diagnostic ignored "-Wunused-function"
// 上面的是速度优化指令,可以删除,但速度会慢一点
typedef long double ld; // 这里选择long double,你也可以用其他的
ld sqrt(ld n,ld x){ // n代表要开根号的数,x代表你选的初始值(x不能为非正整数)
ld eqs=1e-19; // eqs表示最大可以接受的误差,如有需求可调整
while(abs(x*x-n))x=(x*x+n)/(2*x); // 公式计算
return x; // 最后返回x
}
int main(){
ld n;
cin>>n;
printf("%.20Lf\n", sqrt(n,1)); // 这里x初始值选了1,初始值、输出精度如有需求可调整(养成换行好习惯)
return 0;
}
如果你追求极致速度的话,我这里也是有一个四阶收敛的超级公式,具体公式如下:
x=x-(x*x-n)/(x+x*n/(x*x+n)+(x*x+n)/(4*x))
代码示范:
#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("Ofast", "unroll-loops", "no-stack-protector", "fast-math")
#pragma GCC target("avx2", "avx512f", "avx512vl", "fma", "bmi2", "popcnt")
#pragma GCC diagnostic ignored "-Wunused-function"
// 上面的是速度优化指令,可以删除,但速度会慢一点
typedef long double ld; // 这里选择long double,你也可以用其他的
ld sqrt(ld n,ld x){ // n代表要开根号的数,x代表你选的初始值(x不能为非正整数)
ld eqs=1e-19; // eqs表示最大可以接受的误差,如有需求可调整
while(abs(x*x-n))x=x-(x*x-n)/(x+x*n/(x*x+n)+(x*x+n)/(4*x)); // 公式计算
return x; // 最后返回x
}
int main(){
ld n;
cin>>n;
printf("%.20Lf\n", sqrt(n,1)); // 这里x初始值选了1,初始值、输出精度如有需求可调整(养成换行好习惯)
return 0;
}
最后顺便提一嘴:__float128等扩展类型不能用普通cout/cin、printf/scanf 输出/输入,你得自己定义输出输入方式
如有更快的收敛公式,也欢迎大家留言讨论!
课后作业:用我讲到的任意方法心算/笔算出 根号10的 前10位小数。
下课!
全部评论 5
sqrt精度不够不是应该学习sqrtl函数吗

昨天 来自 广东
1天才
昨天 来自 广东
0orz
昨天 来自 浙江
0
豪中之豪,acgo最肥的区,最恶的瘤
昨天 来自 广东
0nbnb
昨天 来自 广东
0攻击力拉满了
昨天 来自 广东
0好恶毒
昨天 来自 浙江
0
一道题必须提交一万次之人
昨天 来自 广东
0永远只写傻福题目之人
昨天 来自 广东
0垃圾,乐子,fw
昨天 来自 广东
0



























有帮助,赞一个