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);//这里好像四舍五入,再去掉零,最后得到想要的结果,
c++

3个回答

// 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万。

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

lnhv013710
lnhv013710 谢谢大家帮忙,抱歉,大家的代码都看不懂,但是1楼的赞多,用了1楼的代码,分数送给1楼了,再次感谢
8 个月之前 回复
devmiao
见了你女王大人喵姐还不跪下 回复请你们大家多多姿瓷我菠菜菌: 这个程序最正宗了,虽然有点笔误,但是一看就是最好的。
8 个月之前 回复
dabocaiqq
请多多姿瓷阿木小镇 有一个小错误 else sprintf(buffer, "%d.%d0", x, y / 10); 这里少了一个0
8 个月之前 回复

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

#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万次,不是很多次吧,要多少时间,慢不慢?

lnhv013710
lnhv013710 谢谢大家帮忙,抱歉,大家的代码都看不懂,但是1楼的赞多,用了1楼的代码,分数送给1楼了,再次感谢
8 个月之前 回复

首先第一个你的做法是:
先将字符串转换成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;
}

运行结果:
图片说明

lnhv013710
lnhv013710 谢谢大家帮忙,抱歉,大家的代码都看不懂,但是1楼的赞多,用了1楼的代码,分数送给1楼了,再次感谢
8 个月之前 回复
dabocaiqq
请多多姿瓷阿木小镇 回复见了你女王大人喵姐还不跪下: 说的对,给你点赞
8 个月之前 回复
devmiao
见了你女王大人喵姐还不跪下 说一句公道话,这个程序确实有点慢,稳定性也差,但是比较简单,适合学校学生考试的时候使用。
8 个月之前 回复
dabocaiqq
请多多姿瓷阿木小镇 回复liujianchen_linux: 看我补充的回答,就知道为什么说你专门骗积分素质非常差了
8 个月之前 回复
liujianchen_linux
liujianchen_linux 回复liujianchen_linux: 我的目的是为了给别人解决问题的,而不是像你一样为了骗分不择手段,我的答案对错你又没有验证过,怎么能直接就说不对呢,我只是给了提问者一个思路,采不采纳都是题主自己的选择呀...
8 个月之前 回复
liujianchen_linux
liujianchen_linux 回复请你们大家多多姿瓷我菠菜菌: 你这种人素质是真的低
8 个月之前 回复
dabocaiqq
请多多姿瓷阿木小镇 回复liujianchen_linux: 你都修改了好几次都没有改出来,看我的程序
8 个月之前 回复
liujianchen_linux
liujianchen_linux 回复请你们大家多多姿瓷我菠菜菌: ??????????
8 个月之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问