lnhv013710
2019-06-15 23:07
采纳率: 96.7%
浏览 504

vs2010 MFC 问一个关于浮点数小数点的处理

我需要处理的数据范围是0-1999.99,这个是在浮点的精度范围内的。
例如如,会遇到如下字符串:
0.00077777->0
0.200000->0.2
2.00000->2
2.55555->2.55
1000.66666->1000.66
1999.00000->1999
->后面是最后想要的字符。
我目前用的下面的办法,我担心这样转换最终会在Section2中出现科学计数法e。不知哪位大神帮我看看能不能行。或者有其他更好的方法

        CString strTemp,Section2
            FLOAT XX=atof(strTemp);  //必须先转浮点数,用来计算。
            strTemp.Format("%.2f",XX); //先转化成字符,截断,保留小数点后两位。
                XX=atof(strTemp);    //再转化成浮点,因为浮点,这里不会小数点后两位。
                Section2.Format("X=%g",XX);//这里好像四舍五入,再去掉零,最后得到想要的结果,
  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • threenewbee 2019-06-16 09:25
    已采纳
    // Q766008.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include "Q766008.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    /////////////////////////////////////////////////////////////////////////////
    // The one and only application object
    
    CWinApp theApp;
    
    using namespace std;
    
    void conv1(double d, int* a, int *b)
    {
        // int id = (int)(d * 100 + 0.5);如果要四舍五入,用这个
        int id = (int)(d * 100);
        *a = id / 100;
        *b = id % 100;
    }
    
    void conv(double d, char * buffer)
    {
        int x;
        int y;
        conv1(d, &x, &y);
        if (x == 0 && y == 0)
        {
            sprintf(buffer, "0");
        }
        else if (y == 0)
        {
            sprintf(buffer, "%d", x);
        }
        else if (y < 10)
        {
            sprintf(buffer, "%d.0%d", x, y);
        }
        else
        {
            if (y % 10 != 0)
                sprintf(buffer, "%d.%d", x, y);
            else
                sprintf(buffer, "%d.%d", x, y / 10);
        }
    
    }
    
    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
        int nRetCode = 0;
    
        // initialize MFC and print and error on failure
        if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
        {
            // TODO: change error code to suit your needs
            cerr << _T("Fatal Error: MFC initialization failed") << endl;
            nRetCode = 1;
        }
        else
        {
            // TODO: code your application's behavior here.
            //CString strHello;
            //strHello.LoadString(IDS_HELLO);
            //cout << (LPCTSTR)strHello << endl;
            double arr[] = { 0.00077777, 0.200000, 2.00000, 2.55555, 1000.66666, 1999.00000 };
            for (int i = 0; i < 6; i++)
            {
                char buffer[100];
                conv(arr[i], buffer);
                CString str = (CString)buffer;
                cout << (LPCTSTR)str << endl;
            }
    
        }
    
        return nRetCode;
    }
    
    
    

    0
    0.2
    2
    2.55
    1000.66
    1999
    Press any key to continue

    本代码的限制:
    转换的值必须是>=0
    转换的值必须小于2100万。

    可以保证在以上条件下满足你的需求

    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • Next66 2019-06-17 09:29

    首先第一个你的做法是:
    先将字符串转换成float,然后通过转换成字符串的方式获得保留2位小数后的字符串,最后将字符串再转化为float;
    其实完全可以简化下:
    先处理字符串,直接保留字符串小数量后的2位字符,然后再转换成float就行了

    还有一个问题就是你怕Section2.Format("X=%g",XX)会以指数形式输出; 这个是不会的 因为你的范围是0-1999.99,具体参考https://blog.csdn.net/you_shou/article/details/51198615

    我写了个测试代码了看下是否能用上吧,我用的是通过正则表达式去掉小数点后2位后的所有字符:

    #include<iostream>
    #include<regex>
    int main(void){
        std::string str = "1999.9957819";
        std::regex pattern("(.*?\\.\\d{2})(.*?)$");
        str = std::regex_replace(str, pattern,"$1"); 
        std::cout << str << std::endl;
        float ft = atof(str.c_str());
        printf("%g",ft);
        return 0;
    }
    

    运行结果:
    图片说明

    评论
    解决 无用
    打赏 举报
  • dabocaiqq 2019-06-17 09:39

    辛苦编写代码不容易,这个代码没有使用正则表达式,因此效率上可以保证,而且杜绝了不同平台正则表达式解析差异导致的程序结果不一致。是最完美的办法,请采纳一下,以后会多多回你的问题。

    #include "stdio.h"
    #include "string.h"
    
    //将字符串转换为定点数,int存储定点数,pos存储定点数的模
    void str2Dec(char* str, int* val, int* pos)
    {
        *val = 0;
        *pos = 0;
        for (int i = 0; i < strlen(str); i++)
        {
            if (str[i] == '.')
            {
                *pos = 1;
            }
            else
            {
                *val *= 10;
                *val += (str[i] - '0');
                if (*pos != 0) *pos *= 10;
            }
        }
        if (*pos == 0) *pos = 1;
    }
    
    //这里借鉴下前面专家的代码
    void conv(int x, int y, char * buffer)
    {
        if (x == 0 && y == 0)
        {
            sprintf(buffer, "0");
        }
        else if (y == 0)
        {
            sprintf(buffer, "%d", x);
        }
        else if (y < 10)
        {
            sprintf(buffer, "%d.0%d", x, y);
        }
        else
        {
            if (y % 10 != 0)
                sprintf(buffer, "%d.%d", x, y);
            else
                sprintf(buffer, "%d.%d0", x, y / 10);
        }
    
    }
    
    int main(int argc, char* argv[])
    {
        char * s = "1.123111";
        char x[100];
        int v, p;
        str2Dec(s, &v, &p);
        conv(v / p, (v * 100 / p) % 100, x);
        printf("%s\n", x);
    
        return 0;
    }
    
    

    为什么说有一个人是回答错误
    首先
    regex不是所有编译器都支持
    图片说明
    其次,regex在一些情况下造成内存泄漏,不能实现可靠的代码
    最后,这个不用我说,lz自己测试下

    #include <iostream>
    #include <sstream>
    #include <string>
    #include<regex>
    
    using namespace std;
    template <class T> 
    std::string ConvertToString(T value) {
      stringstream ss;
      ss << value;
      return ss.str();
    }
    
    int main(void){
        for (int i = 0; i < 99999; i++)
        {
        std::string str = ConvertToString(i);
        str = "0." + str;
        std::regex pattern("(.*?\\.\\d{2})(.*?)$");
        str = std::regex_replace(str, pattern,"$1"); 
        std::cout << str << " ";
        float ft = atof(str.c_str());
        printf("%g\n",ft);
        }
        return 0;
    }
    

    转换10万次,不是很多次吧,要多少时间,慢不慢?

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题