📄 floatutils.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 + -