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

📄 floatutils.cpp

📁 浮点数处理包
💻 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 + -