1

我的软件必须向用户显示最终结果,通过 UART 端口接收数据,然后我需要对数据进行格式化和舍入。

我确实写了算法来做到这一点,但我的感觉是必须有一个更好的解决方案。

我的输出可以有多个范围,我需要正确舍入和格式化。

例子:

许多结果中有 1 个来自 ->

0.000 欧姆至 2.000 欧姆

2.01 欧姆至 20.00 欧姆

20.1 欧姆至 100.0 欧姆

100 欧姆至 200 欧姆

我做了一个简单的结构来保存格式化的基本数据

struct _range
{
  float from; //0.000 for first example 
  float to; //2.000 
  int decimal; //3, decimal places I need
  int unit; //Unit to format, Ohm in my example
  float div; //sometimes I need to divide the result at some range
  //example, when I reach 1000VA I need to divide by 1000 to get 1kVA
};

我有一个名为 AddUnitToResult 的静态函数,这个函数会将单位添加到我的结果中。

现在我请您帮助我编写一个函数,该函数将正确地将结果格式化为字符串并将其舍入为双精度(我需要双精度以便稍后进行比较)。

正确格式化意味着即使结果为 0,也应该将其格式化为 3 个十进制位置。

我希望你能帮助我伙计们

编辑:

这是我目前必须处理的舍入和除法。

void ResultBox::SetResult(float res)
{
    this->measureCounter++;
    this->valueAVG +=res;
    if (res > this->valueMax)
        this->valueMax = res;
    if (res < this->valueMin)
        this->valueMin = res;


    float tttmp;
    if (this->RangeCount > 0 && this->ranges[0].decimal >= 0)
    {
        tttmp = Converter::cutDecimal(res,this->ranges[0].decimal);
    }




    int decimal = GetDecimalPlaces(res,0);

    float div = GetDivision(res);

    int unit = GetUnit(res);
    tttmp=tttmp/div;
    this->result = tttmp;

    float tmpRes = res /div; 
    this->isValid =true;

    WCHAR resText[20];
    WCHAR finalText[20];
    WCHAR maxText[20];
    WCHAR minText[20];

    char resTEXT[20];

    tmpRes = res/div;;

    std::ostringstream ss;
    ss << std::fixed << std::setprecision(decimal) << tttmp;
    std::string s = ss.str();
    if (decimal > 0 && s[s.find_last_not_of('0')] == '.')
    {

        s.erase(s.size()-decimal+1);
    }



    Converter::dtoa(resTEXT,tmpRes);
    switch(decimal)
    {
    case 0:
        if (floor(tttmp) == tttmp)
        {
            swprintf(resText,L"%.0f",tttmp);
        }else
        {
            swprintf(resText,L"%S",s.c_str());
        }

        swprintf(maxText,L"%.0f",this->GetMax());
        swprintf(minText,L"%.0f",this->GetMin());
        break;
    case 1:
        if (floor(tttmp) == tttmp)
        {
            swprintf(resText,L"%.1f",tttmp);
        }else
        {
            swprintf(resText,L"%S",s.c_str());
        }

        swprintf(maxText,L"%.1f",this->GetMax());
        swprintf(minText,L"%.1f",this->GetMin());
        break;
    case 2:
        if (floor(tttmp) == tttmp)
        {
            swprintf(resText,L"%.2f",tttmp);
        }else
        {
            swprintf(resText,L"%S",s.c_str());
        }

        swprintf(maxText,L"%.2f",this->GetMax());
        swprintf(minText,L"%.2f",this->GetMin());
        break;
    case 3:
        if (floor(tttmp) == tttmp)
        {
            swprintf(resText,L"%.3f",tttmp);
        }else
        {
            swprintf(resText,L"%S",s.c_str());
        }

        swprintf(maxText,L"%.3f",this->GetMax());
        swprintf(minText,L"%.3f",this->GetMin());
        break;
    case 4:
        if (floor(tttmp) == tttmp)
        {
            swprintf(resText,L"%.4f",tttmp);
        }else
        {
            swprintf(resText,L"%S",s.c_str());
        }

        swprintf(maxText,L"%.4f",this->GetMax());
        swprintf(minText,L"%.4f",this->GetMin());
        break;
    case 5:
        if (floor(tttmp) == tttmp)
        {
            swprintf(resText,L"%.5f",tttmp);
        }else
        {
            swprintf(resText,L"%S",s.c_str());
        }

        swprintf(maxText,L"%.5f",this->GetMax());
        swprintf(minText,L"%.5f",this->GetMin());
        break;
    }


    //pogledamo če je majni
    if (res < this->GetMin())
    {
        if (LowerEnabled == true)
        {
            wcscpy(finalText,L"<");
        }
        else
        {
            wcscpy(finalText,L"");
        }
        wcscat(finalText,minText);
    }
    else if (res > this->GetMax())
    {
        wcscpy(finalText,L">");
        wcscat(finalText,maxText);
    }
    else
    {
        wcscpy(finalText,resText);
    }
    if (res == this->GetMin())
    {
        wcscpy(finalText,minText);
    }
    if (res == this->GetMax())
    {
        wcscpy(finalText,maxText);
    }

    if (this->unitBox)
    {
        WCHAR mm[10];
        wcscpy(mm,L"");
        TABSGuiProxy::MargeResultAndUnit(mm,unit);
        if (mm[0] == ' ')
            this->unitBox->SetText(&mm[1]);
        else
            this->unitBox->SetText(mm);
    }

    this->m_ptextBlock->SetText(finalText);
    if (this->resultLimit)
    {
        if (unit == MEASRUEMENT_UNITS::kVA)
        {
            float fff = this->resultLimit->GetValue()*1000;
            std::wostringstream ss1;
            ss1 << std::fixed << std::setprecision(decimal) << fff;
            std::wstring s1 = ss1.str();
            if (decimal > 0 && s1[s1.find_last_not_of('0')] == '.')
            {
                s1.erase(s1.size()-decimal+1);
            }

            if (wcscmp(resText,s1.c_str()) == 0)
            {

                this->SetGoodResult();
            }else
            {
                float mmm = fabs(_wtof(s1.c_str()) - this->resultLimit->GetValue()*1000) ;
                //else if (fabs(IDelResoult - IDeltaLim) <= 0.001 || IDelResoult < IDeltaLim)
                if (mmm<= 0.001 || tttmp < (_wtof(s1.c_str())))
                {
                    this->SetGoodResult();
                }
                else
                {
                    this->SetBadResult();
                }
            }
        }
        else
        {
            float fff = this->resultLimit->GetValue();
            std::wostringstream ss1;
            ss1 << std::fixed << std::setprecision(decimal) << fff;
            std::wstring s1 = ss1.str();
            if (decimal > 0 && s1[s1.find_last_not_of('0')] == '.')
            {
                s1.erase(s1.size()-decimal+1);
            }

            if (wcscmp(resText,s1.c_str()) == 0)
            {

                this->SetGoodResult();
            }
            else
            {
                float mmm = fabs(_wtof(resText) - this->resultLimit->GetValue()) ;
                //else if (fabs(IDelResoult - IDeltaLim) <= 0.001 || IDelResoult < IDeltaLim)
                if (mmm<= 0.001 || tttmp < (_wtof(s1.c_str())))
                {
                    this->SetGoodResult();
                }
                else
                {
                    this->SetBadResult();
                }
            }
        }
    }

}

让我试着解释一下:

我使用 struct _range 为我的输出设置有效范围,当我初始化结果时,我创建了多个范围类型的结构。

假设我有:

范围 1 -> 0.000 至 2.000 欧姆 范围2 -> 2.01 至 20.00 欧姆 范围3 -> 20.1 至 100.0 欧姆 范围4 -> 101 至 200 欧姆

当我初始化我的结果时,我创建了一个由 4 个结构组成的数组,每个结构都包含这些数据

Range1 -> 
struct _range
{
  float from    = 0.000 
  float to      = 2.000
  int   decimal =3;
  int   unit        = Ohm; //Unit to format, Ohm in my example
  float div     =1; 
};

Range2 -> 
struct _range
{
  float from    = 2.01 
  float to      = 20.00
  int   decimal =2;
  int   unit        = Ohm; //Unit to format, Ohm in my example
  float div     =1; 
};

Range3 -> 
struct _range
{
  float from    = 20.1 
  float to      = 100.0
  int   decimal =1;
  int   unit        = Ohm; //Unit to format, Ohm in my example
  float div     =1; 
};

Range4 -> 
struct _range
{
  float from    = 101 
  float to      = 200
  int   decimal =0;
  int   unit        = Ohm; //Unit to format, Ohm in my example
  float div     =1; 
};

现在我的函数的输入可以是 0 到 200,我必须格式化文本并根据结构中的范围舍入浮点数。

我希望这能解释得更多

4

4 回答 4

1

我认为您可以通过在 _range 结构中添加“格式”成员来改进此代码,如下所示:

struct _range
{
  float from; //0.000 for first example 
  float to; //2.000 
  int decimal; //3, decimal places I need
  int unit; //Unit to format, Ohm in my example
  float div; //sometimes I need to divide the result at some range
  //example, when I reach 1000VA I need to divide by 1000 to get 1kVA
  char * format;
};

然后像这样初始化 range 结构的实例:

Range1.from    = 0.000;
Range1.to      = 2.000;
Range1.decimal = 3;
Range1.format  = "%.3f";

Range2.from    = 2.01;
Range2.to      = 20.00;
Range2.decimal = 2;
Range2.format  = "%.2f";

然后在打印值时引用适当范围实例的格式字符串。也许是这样的:

sprintf(pstr, pRangeOfValue->format, value);
于 2013-07-24T13:13:19.697 回答
0
printf("3.3f",variable);

应该可以显示最多 3 位小数。

于 2013-07-23T08:21:30.737 回答
0

您可以在 std::cout 之前在 std 中使用以下函数:

std::setprecision(5)

例如,这将允许将数字四舍五入到小数点后 5 位。

于 2013-07-23T08:16:56.193 回答
0

简单 - 使用 sprintf。例子:

float variable = 0.0f;
const char buffer[ 7 ];
sprintf( buffer, "3.3f", variable ); 
// 3.3f => 3 places before dot and 3 after
// Examples:
//   0.123
//  12.200
// 123.456
于 2013-07-23T08:17:00.320 回答