2013-07-23 3 views
1

Мое программное обеспечение должно показывать конечный результат пользователю, данные принимаются через порт UART, тогда мне нужно форматировать и округлять данные.Правильно форматирование вывода

Я написал algorihtm, чтобы сделать это, но я чувствую, что должно быть лучшее решение.

Мой выход может иметь несколько диапазонов, что мне нужно округлять и форматировать правильно.

Пример:

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 целевых мест.

Я надеюсь, что вы можете помочь мне, ребята

Edit:

Это то, что я в настоящее время приходится работать круглые и разделяющая.

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 установить допустимые диапазоны для моего выхода, когда я INIT результат создать Mutiple-структуру диапазона типа.

Пусть говорят, у меня есть:

Range1 -> 0,000 до 2,000 Ом Range2 -> 2,01 до 20.00 Ом диапазон 3 -> 20,1 до 100,0 Ом Range4 -> 101 до 200 Ом

Когда я INIT моего результата я создаю массив из 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, и я должен форматировать текст и вокруг поплавка в зависимости от диапазонов в структурах.

Я надеюсь, что это объясняет это немного более

+0

Это довольно сложно понять, каков ваш вопрос, так как у вас есть округление, числовые диапазоны и сравнения, все связанные друг с другом. Я считаю, что одна из вещей, которую вы пытаетесь решить, - обеспечить, чтобы числа имели нулевые нули; это решение можно найти здесь: http://stackoverflow.com/questions/277772/avoid-trailing-zeroes-in-printf – Ross

+0

Привет, мой ангел не самый лучший, поэтому мне сложно объяснить, что я хочу, я действительно хотите получить сформированный текст и округленный float, из функции, учитывая все параметры в struct. В настоящее время мой код беспорядок и, по моему мнению, имеет множество исключений, вот почему я прошу о помощи. –

+0

Я не считаю ваш английский проблемой, и я уверен, что ваш английский лучше, чем мой словенский. Трудность состоит в том, что трудно понять масштаб вашей проблемы. Я не могу понять, что из функции «от» до «и» div в функции округления. Предполагается ли, что значения должны быть обрезаны, чтобы быть в диапазоне от «до»? Или, если вы выходите из диапазона, тогда вы «разделите» его? Опять же, общая цель не ясна. – Ross

ответ

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; 
}; 

Затем инициализировать экземпляры диапазона структуры, как это:

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); 
0

Вы можете использовать следующую функцию в станд, прежде чем станд :: соиЬ:

std::setprecision(5) 

Это позволит число быть округлены до 5 знаков после запятой например.

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 
+0

Это работает. Пока вы не говорите, что переменная равна 2.2968 и хотите напечатать до 3 десятичных знаков без дополнительного округления sprintf. –

0
printf("3.3f",variable); 

должны сделать трюк в отображении до 3-х знаков после запятой.

+0

печатьf, делает дополнение округление, что я не хочу. Попробуйте ввести 2.2968; Вот почему у меня проблемы –

+2

@LukaPivk: Что вы подразумеваете под «дополнительным округлением». Он округляется условно к нулю, если следующая цифра <5, в противном случае округляется от нуля. Какое округление вам нужно? Мы могли бы попробовать 2.2968, но неясно, чего вы ожидаете. Я бы ожидал 2.297 - чего вы хотели? – Clifford

Смежные вопросы