C语言中sqrt计算平方根的几种方法C++算法详细解释

代码

#include 
using namespace std;
const double eps = 1e-15;

double sqrtByBisection(double n); // 第一种
double sqrtByNewton(double n); // 第二种
float sqrtHack(float x); // 第三种
float Q_rsqrt(float number); // 变形
float InvSqrt(float x); // 变形

int main() {
	double num;
	cin >> num;
	//cout << sqrtByBisection(num);
	//cout << sqrtByNewton(num);
	//cout << sqrtHack(num);
	//cout << Q_rsqrt(num);
	cout << 1 / InvSqrt(num);
	return 0;
}

double sqrtByBisection(double n) {
	if (n < 0) // 小于 0
		return n;
	double mid, last; // last 保存上一次的计算得到的 mid
	double low = 0, up = n;
	mid = (low + up) / 2;
	do
	{
		if (mid * mid > n) up = mid;
		else low = mid;
		last = mid;
		mid = (up + low) / 2; 
	} while (abs(mid - last) > eps); // 精度控制
	return mid;
}

double sqrtByNewton(double n) { // 牛顿迭代法
	double val = n;
	double last; // 保存上一次的值
	do {
		last = val;
		val = (val + n / val) / 2;		
	} while (abs(val - last) > eps);
	return val;
}

/*
Quake-III Arena (雷神之锤3)是90年代的经典游戏之一。
该系列的游戏不但画面和内容不错,而且即使计算机配置低,
也能极其流畅地运行。
这要归功于它3D引擎的开发者约翰-卡马克(John Carmack)。
*/
float sqrtHack(float x)
{
	float xhalf = 0.5f * x;
	int i = *(int*)&x; // get bits for floating VALUE 
	i = 0x5f375a86 - (i >> 1); // gives initial guess y0
	x = *(float*)&i; // convert bits BACK to float
	x = x * (1.5f - xhalf * x * x); // Newton step, repeating increases accuracy
	x = x * (1.5f - xhalf * x * x); // Newton step, repeating increases accuracy
	x = x * (1.5f - xhalf * x * x); // Newton step, repeating increases accuracy

	return 1 / x;
}

// 在game/code/q_math.c里发现了这样一段代码。
// 它的作用是将一个数开平方并取倒,经测试这段代码比(float)(1.0/sqrt(x))快4倍:
float Q_rsqrt(float number)
{
	long i;
	float x2, y;
	const float threehalfs = 1.5F;
	x2 = number * 0.5F;
	y = number;
	i = *(long*)&y;   // evil floating point bit level hacking
	i = 0x5f3759df - (i >> 1); // what the fuck?
	y = *(float*)&i;
	y = y * (threehalfs - (x2 * y * y)); // 1st iteration
	y = y * (threehalfs - (x2 * y * y)); // 2nd iteration, this can be removed
	y = y * (threehalfs - (x2 * y * y)); // 增加精确度
	#ifndef Q3_VM
	#ifdef __linux__
		assert(!isnan(y)); // bk010122 - FPE?
	#endif
	#endif
	return 1 / y;   // y 为平方根倒数
}

float InvSqrt(float x)
{
	float xhalf = 0.5f * x;
	int i = *(int*)&x; // get bits for floating VALUE 
	i = 0x5f375a86 - (i >> 1); // gives initial guess y0
	x = *(float*)&i; // convert bits BACK to float
	x = x * (1.5f - xhalf * x * x); // Newton step, repeating increases accuracy
	x = x * (1.5f - xhalf * x * x); // Newton step, repeating increases accuracy
	x = x * (1.5f - xhalf * x * x); // Newton step, repeating increases accuracy
	return x;
}

关于雷神三快速求平方根的解释

参考链接

0x5f3759df这个快速开方中的常数的数学依据是什么?

想看各种数如何变成二进制的可以去 IEEE-754 Floating Point Converter 试一下
C语言中sqrt计算平方根的几种方法C++算法详细解释_第1张图片
C语言中sqrt计算平方根的几种方法C++算法详细解释_第2张图片

C语言中sqrt计算平方根的几种方法C++算法详细解释_第3张图片

在这里插入图片描述
C语言中sqrt计算平方根的几种方法C++算法详细解释_第4张图片
C语言中sqrt计算平方根的几种方法C++算法详细解释_第5张图片
C语言中sqrt计算平方根的几种方法C++算法详细解释_第6张图片
C语言中sqrt计算平方根的几种方法C++算法详细解释_第7张图片
C语言中sqrt计算平方根的几种方法C++算法详细解释_第8张图片

浮点数的存储

单精度浮点数float在计算机中如何存储、float所能表示的范围
C语言中sqrt计算平方根的几种方法C++算法详细解释_第9张图片
C语言中sqrt计算平方根的几种方法C++算法详细解释_第10张图片
C语言中sqrt计算平方根的几种方法C++算法详细解释_第11张图片
C语言中sqrt计算平方根的几种方法C++算法详细解释_第12张图片
C语言中sqrt计算平方根的几种方法C++算法详细解释_第13张图片
C语言中sqrt计算平方根的几种方法C++算法详细解释_第14张图片
C语言中sqrt计算平方根的几种方法C++算法详细解释_第15张图片

小结

牛顿迭代法
对数近似值
浮点数存储方式:有效位、指数部分(阶码表示)、有效位
存储的二进制浮点数看成整数

你可能感兴趣的:(小白的算法竞赛,C++学习,小白的数据结构,c++,c语言,算法)