2015-09-08 5 views
0

Мне нужно отформатировать число с плавающей запятой (представленное как std::string), где выход будет иметь 14 цифр с максимальным значением, включая как неотъемлемую часть, так и десятичную часть.Динамическое форматирование номера фиксированной точки

В то время как ограничивается до 14 цифр, интегральная часть может иметь ДО 14 цифр (то есть не дробная часть) и десятичной части может иметь максимум 7 цифр (затем 7 цифр для интегральной части)

**Examples** 
123 
123.456 
123456789
1234567.89 
1234.5678901 
1234567890123.4 
1234567890123.456 // Invalid; Should be transformed to 1234567890123.4 
123456789.6 // Invalid; Should be transformed to 123456789

Идея состоит в том, чтобы сохранить length =< 14, где максимальное число десятичных чисел равно 7. В конце концов, мне также необходимо добавить тысячи разделителей, а также.

Текущий подход В настоящее время я пытаюсь разбить строку с использованием десятичной точки и извлечь две части номера. (Если нет ".", он будет обрабатываться отдельно). Затем размеры проверяются на неотъемлемую часть и десятичную часть.

Однако, поскольку это не прямолинейно, в некоторых случаях это терпит неудачу.

Но мой вопрос:

Есть ли простой способ, что я могу использовать без все этого беспорядка?

+0

Что вы будете делать, если у вас есть более 14 цифр? Что вы делаете, когда у вас более 7 знаков после запятой? Вы округляете или просто усекаетесь? – NathanOliver

+0

Возможно, вы могли бы использовать 'std :: set_precision' вместе с' std :: ostringstream'? –

+0

@NathanOliver: Усечение будет хорошо. –

ответ

1

Это довольно просто и, кажется, работает в соответствии с вашими спецификациями.

std::string format(string str) 
{ 
    // Are there any decimals? 
    int dot = str.find("."); 
    if (dot < 0) 
    { 
     return str.substr(0, 14); 
    } 

    std::string integral = str.substr(0, dot); 
    size_t intlength = integral.length(); 

    // Too long to care about decimals? 
    if (intlength >= 14) 
    { 
     return integral.substr(0, 14); 
    } 

    // Keep at most seven decimals 
    std::string decimals = str.substr(dot + 1, 7); 
    size_t declength = decimals.length(); 

    // Is concatenation short enough? 
    if (intlength + declength <= 14) 
    { 
     return integral + "." + decimals; 
    } 

    return integral + "." + decimals.substr(0, 14 - integral.length()); 
} 
+0

Спасибо, но как я могу добавить тысячи разделителей? –

+0

Хорошо, я использовал 'std :: stringstream' с' ss.imbue (std :: locale ("")) 'и' std :: fixed' на неотъемлемой части (после преобразования в int). Это сработало. Большое спасибо.!! –

1

Вы можете использовать Boost.Format. Вот пример, который проходит ваши тестовые примеры:

#include <iostream> 
#include <iomanip> 

#include <boost/format.hpp> 

int main() 
{ 
    std::vector<std::string> examples = { 
     "123", 
     "123.456", 
     "123456789", 
     "1234567.89", 
     "1234.5678901", 
     "1234567890123.4", 
     "1234567890123.456", 
     "123456789.6" 
    }; 
    std::string format = "%1$.15s"; 
    for (auto example : examples) 
    { 
     std::cout << boost::format(format) % example << "\n"; 
    } 
} 
+0

Nice, но это не ограничивает десятичную часть до 7 или менее цифр. http://coliru.stacked-crooked.com/a/b36f6cf14b462852 – NathanOliver

+0

Мне нужно сделать это с помощью C++, не используя внешние библиотеки. Но все равно спасибо. :) –

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