天天看點

浮點數字元串轉換成浮點數實作(2)

        其實幾年前實作過一個面試題版本的,參考:浮點數字元串轉換成浮點數實作。

        最近因為某些原因又拿了出來,做了一些簡單的修改,支援了前端空格處理,溢出檢測等等,當然精度處理這個難度有點大,沒有特殊處理。另外帶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");
           

 <script type="text/javascript" src="http://js.tongji.linezing.com/3587820/tongji.js"></script>

浮點數字元串轉換成浮點數實作(2)

繼續閱讀