⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 floatutils.h

📁 浮点数处理包
💻 H
字号:
// Floating point utilites
// ***********************
// Round()  Rounds a number to a specified number of digits.
// SigFig() Rounds a number to a specified number of significant figures.
// FloatToText() Converts a floating point number to ascii (without the appended 0's)
// RoundValue() Rounds a floating point number to a long.
// ***********************
// Designed and written by Simon Hughes (shughes@netcomuk.co.uk)
// This code has been fully tested, but should you find any bugs, then please
// let me know. The code is free, but please leave my name and e-mail address intact.
// ***********************
// File: FloatUtils.h
// Date: 30th November 1999
// Notice: If you modify the code in any way and redistribute it, please make a comment.
// ***********************
// Modifications:
// Simon Hughes, 11th September 2000.
// Modified FloatToText to default nNumberOfDecimalPlaces to -1
// Added RoundValue() function.
// ***********************
// Modifications:
// Simon Hughes, 18th November 2003.
// Updated SigFig() to check for 0.0 being passed in as the value as log10f(0) returns NaN
// Added FloatsEqual() function
// Added CalcBase() function
// Added CalcBaseFloat() function
// Added Angle() function
// Added LineLength() function
// Modified RoundValue() function so it is very fast
// Added FloatToInt() 
// Added FP_INV for fast 1/n calculations
// Added CheckRange(), CheckMin(), CheckMax(), Divide() template functions

#ifndef LocalUtils_h
#define LocalUtils_h

// Testing float's for equality. When the operands of operators == and != are
// some form of floating type (float, double, or long double).  Testing for
// equality between two floating point quantities is suspect because of
// round-off error and the lack of perfect representation of fractions.
// The value here is for testing two float values are equivalent within the
// range shown here. The implementation is:
//     if(fabs(a - b) > float_equality) ...
// See FloatsEqual(a, b) function
#define float_equality 1.0e-20f
bool FloatsEqual(const float &a, const float &b);

// Rounds a number to a specified number of digits.
// Number is the number you want to round.
// Num_digits specifies the number of digits to which you want to round number.
// If num_digits is greater than 0, then number is rounded to the specified number of decimal places.
// If num_digits is 0, then number is rounded to the nearest integer.
// Examples
//		ROUND(2.15, 1)		equals 2.2
//		ROUND(2.149, 1)		equals 2.1
//		ROUND(-1.475, 2)	equals -1.48
float Round(const float &number, const int num_digits);
double RoundDouble(double doValue, int nPrecision);

// Rounds X to SigFigs significant figures.
// Examples
//		SigFig(1.23456, 2)		equals 1.2
//		SigFig(1.23456e-10, 2)	equals 1.2e-10
//		SigFig(1.23456, 5)		equals 1.2346
//		SigFig(1.23456e-10, 5)	equals 1.2346e-10
//		SigFig(0.000123456, 2)	equals 0.00012
float SigFig(float X, int SigFigs);

// Converts a floating point number to ascii (without the appended 0's)
// Rounds the value if nNumberOfDecimalPlaces >= 0
CString FloatToText(float n, int nNumberOfDecimalPlaces = -1);

// This function wraps the given number so that it remains within its 
// base. Returns a number between 0 and base - 1.
// For example if the base given was 10 and the parameter was 10 it
// would wrap it so that the number is now a 0. If the number given
// were -1, then the result would be 9. This function can also be
// used everywhere where a number needs to be kept within a certain
// range, for example angles (0 and 360) and radians (0 to TWO_PI).
int CalcBase(const int base, int num);
// Same as CalcBase() above, except using floats
float CalcBaseFloat(const float base, float num);
// Make sure angle is between 0 and 359
int Angle(const int &angle);

// Calculates the length of a line between the following two points
float LineLength(const CPoint &point1, const CPoint &point2);

//lint -save -e*
// Converts a floating point value to an integer, very fast.
inline int RoundValue(float param)
{
	// Uses the FloatToInt functionality
	int a;
	int *int_pointer = &a;

	__asm  fld  param
	__asm  mov  edx,int_pointer
	__asm  FRNDINT
	__asm  fistp dword ptr [edx];

	return a;
}
//lint -restore

// At the assembly level the recommended workaround for the second FIST bug is the same for the first; 
// inserting the FRNDINT instruction immediately preceding the FIST instruction. 
//lint -e{715}
// Converts a floating point value to an integer, very fast.
inline void FloatToInt(int *int_pointer, const float &f) 
{
	__asm  fld  f
	__asm  mov  edx,int_pointer
	__asm  FRNDINT
	__asm  fistp dword ptr [edx];
}

// This is about 2.12 times faster than using 1.0f / n
// r = 1/p
#define FP_INV(r,p) \
{ \
	int _i = 2 * 0x3F800000 - *(int *)&(p); \
	(r) = *(float *)&_i; \
	(r) = (r) * (2.0f - (p) * (r)); \
}

// Makes sure Var is within range
template<class T>
void CheckRange(T &Var, const T &Min, const T &Max)
{
	if(Var < Min)
		Var = Min;
	else
		if(Var > Max)
			Var = Max;
}

// Makes sure Var is >= Min
template<class T>
void CheckMin(T &Var, const T &Min)
{
	if(Var < Min)
		Var = Min;
}

// Makes sure Var is <= Max
template<class T>
void CheckMax(T &Var, const T &Max)
{
	if(Var > Max)
		Var = Max;
}

// Performs a safe division. Checks that b is not zero before division.
template<class T>
inline T Divide(const T &a, const T &b)
{
	if(b != T(0))
		return a / b;
	return T(0);
}

#endif // LocalUtils_h

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -