2009-09-30 18 views
8

Mi programa imprime GRANDES números, como 100363443, hasta un billón, y es un poco difícil de leer, por lo que me gustaría imprimir cualquier número de forma fácil para leer el formularioconvertir números astronómicamente grandes en forma legible para humanos en C/C++

ahora utilizo

printf ("%10ld", number); 

formato

le agradecería un número resultante usando printf. La mayor parte de mi código es C++ sin embargo, no quieren introducir std :: cout, como ya he printf

gracias

+0

¿Cómo le gustaría que se impriman sus números para que sean más fáciles de leer? ¿Dígitos en grupos de tres? ¿Separado por comas? Espacios? –

+0

No tengo un requisito estricto; Supongo que hay comas con dígitos en grupos de 3 ... – vehomzzz

+0

Esta funcionalidad ya está integrada en el objeto std :: ostream. Solo necesita impregnar la transmisión con la configuración correcta. Vea la respuesta de Patrick a continuación. –

Respuesta

12

Uso del apostrophe bandera no estándar en la cadena de formato printf, si tiene esa opción disponible y no le importa perder un poco de portabilidad.

Según mi documentación, la bandera ' está disponible para los sistemas POSIX desde 1997.

Si está en Unix, Linux, Mac, ... usted debe tener ningún problema
Si está en Windows, DOS, iSeries, Android, ... todas las apuestas están apagadas (pero tal vez puedas instalar una capa POSIX en tu sistema).

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

En mi sistema produce este programa:

# %'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

Esta es la única respuesta que hace exactamente lo que quiere Andrei, usando exactamente las herramientas que quiere usar. – Massa

+2

Ojalá fuera estándar. –

+0

exactamente lo que quería. Espero que mi perfil o nombre asuste a cualquiera ... – vehomzzz

7

manera fácil podría convertir a un doble justo antes de la salida y el uso de correo% que los imprimirá en notación científica exponencial. Prueba esto:

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

+1 para mí. Esta sería la forma más sencilla de verlos. Lo único que agregaría es establecer un punto de inflexión. Cualquier cosa más baja que el punto de ruptura, debe formatear como un número normal. –

9

Usted podría utilizar humanize_number(), que utiliza sufijos como k, m, etc., para dejar de lado los dígitos de orden inferior. Esta no es una rutina estándar, por lo que debe d/l la fuente que he vinculado. (Licencia BSD de 2 cláusulas, permite cualquier tipo de uso).

Humanize_number man page.

Humanize_number source code de 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); 

Esto funciona mediante sufijos anexas de la siguiente manera:

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

Esto es probablemente sea mejor. Mi pequeño truco solo funciona, supongo que si eres lo suficientemente raro como para considerar la notación científica "legible por humanos";) –

+2

Una objeción REALMENTE menor: los "prefijos" van antes que las cosas (eso es lo que significa "pre"). Los "sufijos" van detrás de las cosas. 110K usa un sufijo K para significar 110,000. –

+0

Oh, heh. Arreglando ... – DigitalRoss

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

nota de que el número es un flotador

EDIT: o si no te gusta científica He encontrado esto en la red:

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; 

EDITAR 2: Como se ha señalado por Jerry que no necesita la clase coma como anteriormente, esto parece suficiente por sí misma (aunque hay presumiblemente lugares que no dan formato a un gran número en absoluto?):

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

Sí. Usar local es la manera consistente de hacerlo. –

+1

Buena idea, pero debería ser más perezoso: std :: cout.imbue (std :: locale ("")); std :: cout << 123456789 << std :: endl; La configuración regional sin un nombre local utiliza lo que el usuario ha configurado, por lo que (por ejemplo) un usuario con su equipo configurado para convenciones de Estados Unidos obtendría: 123456789 pero haciendo uso de las alemanas obtendría: 123.456.789 y así en. En algunos lugares (por ejemplo, India, IIRC), normalmente no se ven grupos de tres, sino algo así como los primeros cinco (menos significativos) dígitos en un grupo y luego en grupos de dos desde allí. En C, busque localeconv; Es mejor que nada. –

3

Recuerde a la localización (especialmente si está escribiendo una biblioteca).
en Europa (excepto Reino Unido) sería 1.000.000 en lugar de 1.000.000

1

Aquí es un ejemplo he escrito en C recta w/o el uso de la configuración regional. Solo funciona para positivos. (Mucha ayuda de "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 

} 
Cuestiones relacionadas