其实几年前实现过一个面试题版本的,参考:浮点数字符串转换成浮点数实现。
最近因为某些原因又拿了出来,做了一些简单的修改,支持了前端空格处理,溢出检测等等,当然精度处理这个难度有点大,没有特殊处理。另外带E(e)的浮点数字符串也进行了处理。需要特别说明的时候,运行时库里面是有一个类似的转换函数的,写一写只是练练手而已。
头文件
/* -------------------------------------------------------------------------
// 文件名 : KString2Float.h
// 创建者 : magic
// 创建时间 : 2015/7/28 17:36:43
// 功能描述 :
//
// $Id: $
// -----------------------------------------------------------------------*/
#ifndef __KSTRING2FLOAT_H__
#define __KSTRING2FLOAT_H__
#include <float.h>
#include <windows.h>
// -------------------------------------------------------------------------
namespace NSUtil
{
// -------------------------------------------------------------------------
// 函数 : atofloat
// 功能 : 将一个字符串转换为浮点数
// 返回值 : float
// 参数 : const char* s
// 附注 :
// -------------------------------------------------------------------------
float atofloat(const char* s);
// -------------------------------------------------------------------------
// 函数 : wtofloat
// 功能 : 将一个宽字符串转换为浮点数
// 返回值 : float
// 参数 : const wchar_t* s
// 附注 :
// -------------------------------------------------------------------------
float wtofloat(const wchar_t* s);
// -------------------------------------------------------------------------
// 函数 : strtofloatT
// 功能 : 将一个字符串转换为浮点数
// 返回值 : float
// 参数 : const tchar* s
// 附注 :
// -------------------------------------------------------------------------
template<typename tchar>
float strtofloatT(const tchar* s)
{
// check
if (!s)
return 0.0f;
float fResult = 0.0f; // 存储结果
tchar c = 0;
// 整数部分
bool bNegative = false;
float fInteger = 0.0f;
// 小数部分
bool bDec = false;
float fDecimal = 0.0f;
float fDecPower = 0.1f;
// 指数部分
bool bMeetE = false;
bool bEInFirst = true; // e不能在最前面
bool bNegativeExponent = false;
unsigned int nIntegerExponent = 0;
float fExponentData = 1.0f;
c = *s++;
/* skip whitespace */
while (0x20 == c)
c = *s++;
// 进行首位判断,判断是否是负数
if (0x2d == c)
{
bNegative = true;
c = *s++;
}
else if (0x2b == c)
{
bNegative = false;
c = *s++;
}
while (0 != c)
{
if (bMeetE)
{
// 指数部分
if (c >= 0x30 && c <= 0x39)
{
nIntegerExponent = nIntegerExponent * 10 + c - 0x30;
}
else
{
break;
}
}
else
{
if (0x65 == c || 0x45 == c)
{
if (bEInFirst)
break;
// 确定指数的符号
c = *s;
if (0 == c)
break;
if (0x2d == c)
{
bNegativeExponent = true;
c = *s++;
}
else if (0x2b == c)
{
bNegativeExponent = false;
c = *s++;
}
bMeetE = true;
}
else if (bDec)
{
bEInFirst = false;
// 小数部分
if (c >= 0x30 && c <= 0x39)
{
fDecimal += (c - 0x30) * fDecPower;
fDecPower = fDecPower * 0.1f;
}
else
{
break;
}
}
else
{
bEInFirst = false;
// 整数部分
if (c >= 0x30 && c <= 0x39)
{
fInteger = fInteger * 10.0f + c - 0x30;
}
else if (c == 0x2e)
{
bDec = true;
}
else
{
break;
}
}
}
c = *s++;
}
// 指数处理
if (bMeetE)
{
float fExponent = bNegativeExponent ? 0.1f : 10.0f;
while (nIntegerExponent > 0)
{
fExponentData *= fExponent;
--nIntegerExponent;
}
}
// 溢出检测
fResult = (bNegative? -(fInteger + fDecimal) : fInteger + fDecimal);
fResult *= fExponentData;
if (fResult > FLT_MAX)
{
fResult = FLT_MAX;
}
else if (fResult < -FLT_MAX)
{
fResult = -FLT_MAX;
}
else if (fResult > 0 && fResult < FLT_MIN)
{
fResult = FLT_MIN;
}
else if (fResult < 0 && fResult > -FLT_MIN)
{
fResult = -FLT_MIN;
}
return fResult;
}
#if defined(UNICODE) || defined(_UNICODE)
#define strtofloat wtofloat
#else
#define strtofloat atofloat
#endif // !UNICODE
} // end NSUtil
// -------------------------------------------------------------------------
// $Log: $
#endif /* __KSTRING2FLOAT_H__ */
实现代码
/* -------------------------------------------------------------------------
// 文件名 : KString2Float.cpp
// 创建者 : magic
// 创建时间 : 2015/7/28 17:36:48
// 功能描述 :
//
// $Id: $
// -----------------------------------------------------------------------*/
#include "stdafx.h"
#include "KString2Float.h"
// -------------------------------------------------------------------------
namespace NSUtil
{
// -------------------------------------------------------------------------
// 函数 : atofloat
// 功能 : 将一个字符串转换为浮点数
// 返回值 : float
// 参数 : const char* s
// 附注 :
// -------------------------------------------------------------------------
float atofloat(const char* s)
{
// check
if (!s)
return 0.0f;
float fResult = 0.0f; // 存储结果
char c = 0;
// 整数部分
bool bNegative = false;
float fInteger = 0.0f;
// 小数部分
bool bDec = false;
float fDecimal = 0.0f;
float fDecPower = 0.1f;
// 指数部分
bool bMeetE = false;
bool bEInFirst = true; // e不能在最前面
bool bNegativeExponent = false;
unsigned int nIntegerExponent = 0;
float fExponentData = 1.0f;
c = *s++;
/* skip whitespace */
while (' ' == c)
c = *s++;
// 进行首位判断,判断是否是负数
if ('-' == c)
{
bNegative = true;
c = *s++;
}
else if ('+' == c)
{
bNegative = false;
c = *s++;
}
while ('\0' != c)
{
if (bMeetE)
{
// 指数部分
if (c >= '0' && c <= '9')
{
nIntegerExponent = nIntegerExponent * 10 + c - '0';
}
else
{
break;
}
}
else
{
if ('e' == c || 'E' == c)
{
if (bEInFirst)
break;
// 确定指数的符号
c = *s;
if ('\0' == c)
break;
if ('-' == c)
{
bNegativeExponent = true;
c = *s++;
}
else if ('+' == c)
{
bNegativeExponent = false;
c = *s++;
}
bMeetE = true;
}
else if (bDec)
{
bEInFirst = false;
// 小数部分
if (c >= '0' && c <= '9')
{
fDecimal += (c - '0') * fDecPower;
fDecPower = fDecPower * 0.1f;
}
else
{
break;
}
}
else
{
bEInFirst = false;
// 整数部分
if (c >= '0' && c <= '9')
{
fInteger = fInteger * 10.0f + c - '0';
}
else if (c == '.')
{
bDec = true;
}
else
{
break;
}
}
}
c = *s++;
}
// 指数处理
if (bMeetE)
{
float fExponent = bNegativeExponent ? 0.1f : 10.0f;
while (nIntegerExponent > 0)
{
fExponentData *= fExponent;
--nIntegerExponent;
}
}
// 溢出检测
fResult = (bNegative? -(fInteger + fDecimal) : fInteger + fDecimal);
fResult *= fExponentData;
if (fResult > FLT_MAX)
{
fResult = FLT_MAX;
}
else if (fResult < -FLT_MAX)
{
fResult = -FLT_MAX;
}
else if (fResult > 0 && fResult < FLT_MIN)
{
fResult = FLT_MIN;
}
else if (fResult < 0 && fResult > -FLT_MIN)
{
fResult = -FLT_MIN;
}
return fResult;
}
// -------------------------------------------------------------------------
// 函数 : wtofloat
// 功能 : 将一个宽字符串转换为浮点数
// 返回值 : float
// 参数 : const wchar_t* s
// 附注 :
// -------------------------------------------------------------------------
float wtofloat(const wchar_t* s)
{
// check
if (!s)
return 0.0f;
float fResult = 0.0f; // 存储结果
wchar_t c = 0;
// 整数部分
bool bNegative = false;
float fInteger = 0.0f;
// 小数部分
bool bDec = false;
float fDecimal = 0.0f;
float fDecPower = 0.1f;
// 指数部分
bool bMeetE = false;
bool bEInFirst = true; // e不能在最前面
bool bNegativeExponent = false;
unsigned int nIntegerExponent = 0;
float fExponentData = 1.0f;
c = *s++;
while (L' ' == c)
c = *s++; /* skip whitespace */
// 进行首位判断,判断是否是负数
if (L'-' == c)
{
bNegative = true;
c = *s++;
}
else if (L'+' == c)
{
bNegative = false;
c = *s++;
}
while (L'\0' != c)
{
if (bMeetE)
{
// 指数部分
if (c >= '0' && c <= '9')
{
nIntegerExponent = nIntegerExponent * 10 + c - '0';
}
else
{
break;
}
}
else
{
if ('e' == c || 'E' == c)
{
if (bEInFirst)
break;
// 确定指数的符号
c = *s;
if ('\0' == c)
break;
if ('-' == c)
{
bNegativeExponent = true;
c = *s++;
}
else if ('+' == c)
{
bNegativeExponent = false;
c = *s++;
}
bMeetE = true;
}
else if (bDec)
{
bEInFirst = false;
// 小数
if (c >= L'0' && c <= L'9')
{
fDecimal += (c - L'0') * fDecPower;
fDecPower = fDecPower * 0.1f;
}
else
{
return (bNegative? -(fInteger + fDecimal): fInteger + fDecimal);
}
}
else
{
bEInFirst = false;
// 整数
if (c >= L'0' && c <= L'9')
{
fInteger = fInteger * 10.0f + c - L'0';
}
else if (c == L'.')
{
bDec = true;
}
else
{
return (bNegative? -fInteger : fInteger);
}
}
}
c = *s++;
}
// 指数处理
if (bMeetE)
{
float fExponent = bNegativeExponent ? 0.1f : 10.0f;
while (nIntegerExponent > 0)
{
fExponentData *= fExponent;
--nIntegerExponent;
}
}
// 溢出检测
fResult = (bNegative? -(fInteger + fDecimal) : fInteger + fDecimal);
fResult *= fExponentData;
if (fResult > FLT_MAX)
{
fResult = FLT_MAX;
}
else if (fResult < -FLT_MAX)
{
fResult = -FLT_MAX;
}
else if (fResult > 0 && fResult < FLT_MIN)
{
fResult = FLT_MIN;
}
else if (fResult < 0 && fResult > -FLT_MIN)
{
fResult = -FLT_MIN;
}
return fResult;
}
} // end NSUtil
// -------------------------------------------------------------------------
// $Log: $
测试代码
float fffa = .0e-2;
fffa = 0e-2;
fffa = 1e-2;
fffa = 1e+1;
fffa = .1;
float ffff = atof("-545444.5e-10.67f");
ffff = atof("1e-10f");
ffff = atof("1e-");
ffff = atof("1e+");
ffff = atof("1e0");
float aaaa = NSUtil::atofloat("12.34");
aaaa = NSUtil::atofloat("1e-10f");
aaaa = NSUtil::atofloat("-545444.5e-10.67f");
aaaa = NSUtil::atofloat("1e-");
aaaa = NSUtil::atofloat("1e+");
aaaa = NSUtil::atofloat("1E+");
aaaa = NSUtil::atofloat("1e0");
aaaa = NSUtil::atofloat("-545444.5e-10");
aaaa = NSUtil::atofloat("-0.00000545444.5");
aaaa = NSUtil::atofloat("-54544444444444444444444444444444444444.5");
aaaa = NSUtil::atofloat("+1.345");
aaaa = NSUtil::atofloat(" -34.00001");
aaaa = NSUtil::atofloat(" -12.01001 ");
aaaa = NSUtil::atofloat(" 0.33344");
aaaa = NSUtil::atofloat("a23");
aaaa = NSUtil::atofloat("1234");
aaaa = NSUtil::atofloat("12.34");
aaaa = NSUtil::atofloat("12.34.56");
aaaa = NSUtil::atofloat(".34");
aaaa = NSUtil::atofloat("34a");
aaaa = NSUtil::atofloat("34a.456");
aaaa = NSUtil::atofloat("-34");
aaaa = NSUtil::atofloat("-56.34");
aaaa = NSUtil::atofloat("-3.45.67");
aaaa = NSUtil::atofloat("-.45.6a");
aaaa = NSUtil::atofloat("-.");
aaaa = NSUtil::atofloat("-0");
aaaa = NSUtil::atofloat("3.402823467e+38F");
aaaa = NSUtil::atofloat("-54544444444444444444444444444444444444.5");
aaaa = NSUtil::atofloat("5454444445444444444444444444444444444444.5");
aaaa = NSUtil::atofloat("0.0000000000000000000000000000000000000001");
aaaa = NSUtil::atofloat("-0.0000000000000000000000000000000000000001");
aaaa = NSUtil::strtofloatT("1e-10f");
aaaa = NSUtil::strtofloatT("-545444.5e-10.67f");
aaaa = NSUtil::strtofloatT("1e-");
aaaa = NSUtil::strtofloatT("1e+");
aaaa = NSUtil::strtofloatT("1e0");
aaaa = NSUtil::strtofloatT("+1.345");
aaaa = NSUtil::strtofloatT(" -34.00001");
aaaa = NSUtil::strtofloatT(" -12.01001 ");
aaaa = NSUtil::strtofloatT(L"1e-10f");
aaaa = NSUtil::strtofloatT(L"-545444.5e-10.67f");
aaaa = NSUtil::strtofloatT(L"1e-");
aaaa = NSUtil::strtofloatT(L"1e+");
aaaa = NSUtil::strtofloatT(L"1e0");
aaaa = NSUtil::strtofloatT(L"+1.345");
aaaa = NSUtil::strtofloatT(L" -34.00001");
aaaa = NSUtil::strtofloatT(L" -12.01001 ");
aaaa = NSUtil::wtofloat(L"1e-10f");
aaaa = NSUtil::wtofloat(L"-545444.5e-10.67f");
aaaa = NSUtil::wtofloat(L"1e-");
aaaa = NSUtil::wtofloat(L"1e+");
aaaa = NSUtil::wtofloat(L"1e0");
aaaa = NSUtil::wtofloat(L"+1.345");
aaaa = NSUtil::wtofloat(L" -34.00001");
aaaa = NSUtil::wtofloat(L" -12.01001 ");
aaaa = NSUtil::wtofloat(L" 0.33344");
aaaa = NSUtil::wtofloat(L"a23");
aaaa = NSUtil::wtofloat(L"1234");
aaaa = NSUtil::wtofloat(L"12.34");
aaaa = NSUtil::wtofloat(L"12.34.56");
aaaa = NSUtil::wtofloat(L".34");
aaaa = NSUtil::wtofloat(L"34a");
aaaa = NSUtil::wtofloat(L"34a.456");
aaaa = NSUtil::wtofloat(L"-34");
aaaa = NSUtil::wtofloat(L"-56.34");
aaaa = NSUtil::wtofloat(L"-3.45.67");
aaaa = NSUtil::wtofloat(L"-.45.6a");
aaaa = NSUtil::wtofloat(L"-.");
aaaa = NSUtil::wtofloat(L"-0");