1. 程式人生 > >一種高速開平方並取倒數算法

一種高速開平方並取倒數算法

vs2005 fontsize 倒數 clas 耗時 tick 出現 hal 浪費

今天在查資料過程中,無意中看到這樣一段奇妙的代碼。決定轉載到自己的csdn博客,可是找了半天。楞是沒找到csdn轉載功能。此前常常看到別人轉載文章。然後心裏一直在想,是不是轉載是一個隱藏功能,或者使用什麽命令就能夠了。於是特意谷歌了下,原來csdn的轉載功能,根本沒有什麽高速轉載、一鍵轉載,僅僅有對著原文復制、粘貼,然後在自己的博客裏面又一次排版,最後在公布文章時選擇轉載,這樣該文章就成為一篇轉摘的文章了。

這麽設計也有道理,僅僅有不嫌麻煩的人。才會耐心的完畢轉載,算是提高了轉載的門檻。避免出現大量反復文章。只是,這麽設計的副作用就是,浪費了非常多時間和精力。吐槽就到這裏,還是看看這段奇妙的高速開平方並取倒數代碼:

float InvSqrt(float x )
{
	float xhalf = 0.5f * x;
	int i = *( int *)& x;
	i = 0x5f3759df - ( i>>1);
	x = *( float *)& i;
	x = x * (1.5f - xhalf * x * x);

	return x;
}
關於該段代碼的很多其它說明。請參看這篇文章《0x5f3759df的數學原理》。
以下為我編寫的簡單測試代碼:
#include "stdafx.h"
#include <stdio.h>  
#include <stdlib.h>
#include <windows.h>
#include <math.h>

// 開平方取倒數
float InvSqrt(float x )
{
	float xhalf = 0.5f * x;
	int i = *( int *)& x;
	i = 0x5f3759df - ( i>>1);
	x = *( float *)& i;
	x = x * (1.5f - xhalf * x * x);

	return x;
}

int main()
{
	// 比較精度
	float val = 0.0f;
	val = 1.0f;
	printf("計算精度比較: \n");
	printf("輸入值:   %f    高速算法: %f    VC函數: %f \n", val, InvSqrt(val), 1.0f / sqrt(val));

	val = 16.0f;
	printf("輸入值:  %f    高速算法: %f    VC函數: %f \n", val, InvSqrt(val), 1.0f / sqrt(val));

	val = 25.0f;
	printf("輸入值:  %f    高速算法: %f    VC函數: %f \n", val, InvSqrt(val), 1.0f / sqrt(val));

	val = 100.0f;
	printf("輸入值: %f    高速算法: %f    VC函數: %f \n", val, InvSqrt(val), 1.0f / sqrt(val));

	printf("\n計算性能比較: \n");
	int count = 1000000;
	DWORD timeStart = 0, timeEnd = 0;
	timeStart = GetTickCount();
	for (int i = 0; i < count; i++)  
	{  
		val = InvSqrt(100.0f);  
	}  
	timeEnd  = GetTickCount();  
	printf("高速算法耗時: %f \n", (timeEnd - timeStart) * 0.001); 

	timeStart = GetTickCount();
	for (int i = 0; i < count; i++)  
	{  
		val = 1.0f / sqrt(100.0f);  
	}  
	timeEnd  = GetTickCount();  
	printf("VC函數耗時:   %f \n", (timeEnd - timeStart) * 0.001); 

	printf("\n");
	system("pause");
	return 0;
}
這裏與sqrt()分別比較了計算精度及計算性能,測試環境為vs2005。普通pc筆記本(事實上是一臺年久的、玩的了遊戲、寫得了代碼的小黑)。從對照結果看,該高速算法在計算結果上有一點點誤差,可是計算性能上非常可觀。

下圖為對照結果:
技術分享



一種高速開平方並取倒數算法