2009-09-30 3 views
8

Моя программа печатает огромные цифры - например, 100363443, до триллиона - и это трудно читать, поэтому я хотел бы напечатать любое число в простом читать форму.конвертировать астрономически большие числа в человекообразную форму в C/C++

прямо сейчас я использую

printf ("%10ld", number); 

формат

Я был бы признателен за полученное число с помощью Printf. Большая часть моего кода C++ пока я не хочу вводить зЬй :: COUT, как я уже PRINTF

благодаря

+0

Как бы вы хотели, чтобы ваши номера печатались, чтобы их было легче читать? Цифры в тройках? Разделенных запятыми? Пространства? –

+0

У меня нет строгого требования; Я допускаю запятые с цифрами в группах по 3 ... – vehomzzz

+0

Эта функциональность уже встроена в объект std :: ostream. Вам просто нужно наполнить поток правильными настройками. См. Ответ Патрика ниже. –

ответ

12

Используйте нестандартный apostrophe флага в строке формата Printf, если у вас есть эта опция доступна и не прочь потерять немного переносимости.

Согласно моей документации, то ' флаг доступен для POSIX систем с 1997 года

Если вы на Unix, Linux, Mac OS, ... вы не должны иметь никаких проблем
Если вы на Windows, DOS, iSeries, Android, ... все ставки отключены (но, возможно, вы можете установить POSIX-уровень в свою систему).

#include <locale.h> 
#include <stdio.h> 

int main(void) { 
    long int x = 130006714000000; 

    setlocale(LC_NUMERIC, "en_US.utf-8"); /* important */ 
    while (x > 0) { 
    printf("# %%'22ld: %'22ld\n", x); /* apostrophe flag */ 
    x *= 2; /* on my machine, the Undefined Behaviour for overflow 
      // makes the number become negative with no ill effects */ 
    } 
    return 0; 
} 

В моей системе эта программа производит:

# %'22ld: 130,006,714,000,000 
# %'22ld: 260,013,428,000,000 
# %'22ld: 520,026,856,000,000 
# %'22ld: 1,040,053,712,000,000 
# %'22ld: 2,080,107,424,000,000 
# %'22ld: 4,160,214,848,000,000 
# %'22ld: 8,320,429,696,000,000 
# %'22ld: 16,640,859,392,000,000 
# %'22ld: 33,281,718,784,000,000 
# %'22ld: 66,563,437,568,000,000 
# %'22ld: 133,126,875,136,000,000 
# %'22ld: 266,253,750,272,000,000 
# %'22ld: 532,507,500,544,000,000 
# %'22ld: 1,065,015,001,088,000,000 
# %'22ld: 2,130,030,002,176,000,000 
# %'22ld: 4,260,060,004,352,000,000 
# %'22ld: 8,520,120,008,704,000,000 
+0

Это единственный ответ, который делает именно то, что хочет Андрей, используя именно те инструменты, которые он хочет использовать. – Massa

+2

Я бы хотел, чтобы это было стандартным. –

+0

именно то, что я хотел. Я надеюсь, что мой профиль и имя никого не пугают ... – vehomzzz

7

Легкий способ может преобразовать к двойному как раз перед выходом и использовать% е которые будут печатать их в экспоненциальной научной нотации. Попробуйте это:

double n = (double)number; 
printf("%10.0e", n); 
+1

+1 для меня. Это был бы самый простой способ их просмотра. Единственное, что я хотел бы добавить, это установить точку останова. Все, что ниже точки останова, нужно отформатировать как обычный номер. –

9

Вы можете использовать humanize_number(), который использует суффиксы, как к, м и т.д., чтобы оставить из низких цифр порядка. Это не стандартная процедура, поэтому вы должны использовать d/l источник, с которым я связан. (Лицензия BSD 2-оговорки допускает любые виды использования.)

Humanize_number man page.

Humanize_number source code от NetBSD.

HUMANIZE_NUMBER(3)  NetBSD Library Functions Manual  HUMANIZE_NUMBER(3) 

NAME 
    dehumanize_number, humanize_number -- format a number into a human read- 
    able form and viceversa 

SYNOPSIS 
    #include <stdlib.h> 

    int 
    dehumanize_number(const char *str, int64_t *result); 

    int 
    humanize_number(char *buf, size_t len, int64_t number, 
     const char *suffix, int scale, int flags); 

Это работает путем добавления суффиксов следующим образом:

 Suffix Description Multiplier 
     k   kilo   1024 
     M   mega   1048576 
     G   giga   1073741824 
     T   tera   1099511627776 
     P   peta   1125899906842624 
     E   exa   1152921504606846976 
+1

Это вероятно, лучше. Мой маленький трюк работает только, я думаю, если вы достаточно странны, чтобы считать научную нотацию «понятной человеку».;) –

+2

Один ДЕЙСТВИТЕЛЬНО мелкий каламбур: «префиксы» идут перед вещами (это то, что означает «pre-»). «Суффиксы» идут за вещами. 110K использует суффикс K для обозначения 110 000. –

+0

Ох, хе. Исправление ... – DigitalRoss

6
std::cout << std::setprecision(5) << std::scientific << 100363443.0; 

к сведению, что число является поплавок

EDIT: или, если вам не нравится научная я нашел это на сеть:

struct comma : public std::numpunct<char> 
{ 
    protected: std::string do_grouping() const { return "\003" ; } 
}; 

std::cout.imbue(std::locale(std::cout.getloc(), new comma)); 
std::cout << 100363443 << std::endl; 

EDIT 2: Как отметил Джерри вам не нужен класс разделителей, как указано выше, это, кажется, сами по себе достаточно (хотя есть предположительно локали, не форматировать большое число вообще?):

std::cout.imbue(std::locale("")); 
std::cout << 100363443 << std::endl; 
+0

Да. Использование локального - это последовательный способ сделать это. –

+1

Хорошая идея, но вы должны быть более ленивыми: std :: cout.imbue (std :: locale ("")); std :: cout << 123456789 << std :: endl; Языковой без имени использует стандарт, который пользователь настроил, так (например) пользователь со своим компьютером, сконфигурированной для США конвенций получат: 123,456,789 , но один, используя немецкие конвенции получат: 123.456.789 и так на. В некоторых местах (например, в Индии, IIRC) вы даже не видите группы из трех человек - это что-то вроде первых пяти (наименее значимых) цифр как одна группа, а затем в группах по два оттуда. В C, найдите localeconv; лучше, чем ничего. –

3

Запомни локализации (особенно если вы пишете библиотеку).
В Европе (за исключением Великобритании), было бы 1.000.000, а не 1,000,000

1

Вот пример, который я написал в прямой C без использования локали. Работает только для позитива. (Большая помощь от «DiscoVlad»)

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include <strings.h> 


void my_reverse (char* s) { 
    int c, i, j; 
    for (i=0, j= strlen(s)-1;i<j;i++,j--) { 
     c = s[i]; 
     s[i] = s[j]; 
     s[j] = c; 
    } 
} 


char* insert_commas(unsigned long long input) { 
    int i, intlen; 
    char* buffer; 
    char* formatted; 

    intlen = (int) ceil(log10(input * 1.0)); 
    buffer = (char *) malloc((intlen + 1) * sizeof(char)); 

    sprintf(buffer, "%llu", input); // build buffer 
    formatted = (char *) malloc((intlen + (int) ceil(intlen/3.0)) * sizeof(char)); // malloc output buffer 
    my_reverse(buffer); 

    for(i=intlen; i>=0; i--) { 
     formatted[strlen(formatted)] = buffer[i]; 
     if (i%3 == 0 && i<intlen && i > 0) { 
      formatted[strlen(formatted)] = ','; 
     } 
    } 
    free(buffer); 

    return formatted; 
} 


int main() { 
    char* formatted; 

    // don't forget to free(formatted) after each call. 
    formatted = insert_commas(123); 
    printf("output %s\n", formatted); 
    // output 123 

    formatted = insert_commas(1234); 
    printf("output %s\n", formatted); 
    // output 1,234 

    formatted = insert_commas(123456); 
    printf("output %s\n", formatted); 
    // output 123,456 

    formatted = insert_commas(1234567); 
    printf("output %s\n", formatted); 
    // output 1,234,567 

    formatted = insert_commas(123456789); 
    printf("output %s\n", formatted); 
    // output 123,456,789 

    formatted = insert_commas(123456789ull); 
    printf("output %s\n", formatted); 
    // output 12,345,678,901,234,567,890 

} 

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

  • Нет связанных вопросов^_^