📄 floatutils.cpp
字号:
// 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)
// ***********************
// 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.cpp
// 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.
// Updated the Round() function to use code as provided by Josef Wolfsteiner (Josef.Wolfsteiner@ProSieben.de). Thanks :-)
// Added RoundDouble() to perform the same operation as Round() above, but using double's instead
// ***********************
// 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
#include "Stdafx.h"
#include "FloatUtils.h"
#include <math.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// 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)
{
float doComplete5i, doComplete5(number * powf(10.0f, (float) (num_digits + 1)));
if(number < 0.0f)
doComplete5 -= 5.0f;
else
doComplete5 += 5.0f;
doComplete5 /= 10.0f;
modff(doComplete5, &doComplete5i);
return doComplete5i / powf(10.0f, (float) num_digits);
}
double RoundDouble(double doValue, int nPrecision)
{
static const double doBase = 10.0;
double doComplete5, doComplete5i;
doComplete5 = doValue * pow(doBase, (double) (nPrecision + 1));
if(doValue < 0.0)
doComplete5 -= 5.0;
else
doComplete5 += 5.0;
doComplete5 /= doBase;
modf(doComplete5, &doComplete5i);
return doComplete5i / pow(doBase, (double) 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)
{
if(SigFigs < 1)
{
ASSERT(FALSE);
return X;
}
// log10f(0) returns NaN
if(X == 0.0f)
return X;
int Sign;
if(X < 0.0f)
Sign = -1;
else
Sign = 1;
X = fabsf(X);
float Powers = powf(10.0f, floorf(log10f(X)) + 1.0f);
return Sign * Round(X / Powers, SigFigs) * Powers;
}
// Converts a floating point number to ascii (without the appended 0's)
// Rounds the value if nNumberOfDecimalPlaces >= 0
CString FloatToText(float n, int nNumberOfDecimalPlaces)
{
CString str;
if(nNumberOfDecimalPlaces >= 0)
{
int decimal, sign;
char *buffer = _fcvt((double)n, nNumberOfDecimalPlaces, &decimal, &sign);
CString temp(buffer);
// Sign for +ve or -ve
if(sign != 0)
str = "-";
// Copy digits up to decimal point
if(decimal <= 0)
{
str += "0.";
for(; decimal < 0; decimal++)
str += "0";
str += temp;
} else {
str += temp.Left(decimal);
str += ".";
str += temp.Right(temp.GetLength() - decimal);
}
} else {
str.Format("%-g", n);
}
// Remove appended zero's. "123.45000" become "123.45"
int nFind = str.Find(".");
if(nFind >= 0)
{
int nFinde = str.Find("e"); // 1.0e-010 Don't strip the ending zero
if(nFinde < 0)
{
while(str.GetLength() > 1 && str.Right(1) == "0")
str = str.Left(str.GetLength() - 1);
}
}
// Remove decimal point if nothing after it. "1234." becomes "1234"
if(str.Right(1) == ".")
str = str.Left(str.GetLength() - 1);
return str;
}
// 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 as specified by float_equality.
bool FloatsEqual(const float &a, const float &b)
{
return (fabs(a - b) <= float_equality);
}
// 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)
{
if(num >= 0 && num < base)
return num; // No adjustment neccessary
if(num < 0)
{
num %= base;
num += base;
} else {
num %= base;
}
return num;
}
// Same as CalcBase() above, except using floats
float CalcBaseFloat(const float base, float num)
{
if(num >= 0.0f && num < base)
return num; // No adjustment neccessary
if(num < 0.0f)
return fmodf(num, base) + base;
return fmodf(num, base);
}
// Make sure angle is between 0 and 359
int Angle(const int &angle)
{
return CalcBase(360, angle);
}
// Calculates the length of a line between the following two points
float LineLength(const CPoint &point1, const CPoint &point2)
{
const CPoint dist(point1 - point2);
return sqrtf(float((dist.x * dist.x) + (dist.y * dist.y)));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -