8
votes

convertir des nombres astronomiquement grands en forme lisible humaine en C / C ++

Mon programme imprime des nombres énormes - comme 100363443, jusqu'à un billion de dollars - et il est difficile de les lire, alors je voudrais imprimer n'importe quel nombre dans un formulaire facile à lire.

En ce moment, j'utilise xxx

format

J'apprécierais un numéro résultant à l'aide de printf. La majeure partie de mon code est C ++ pourtant, je ne veux pas introduire std :: Cout, comme je dispose déjà de printf

merci


8 commentaires

Comment voudriez-vous que vos chiffres soient imprimés pour les rendre plus faciles à lire? Chiffres en groupes de trois? Séparé par des virgules? Les espaces?


Je n'ai pas une exigence stricte; Je suppose des virgules avec des chiffres en groupes de 3 ...


Cette fonctionnalité est déjà intégrée à l'objet STD :: Ostream. Vous avez juste besoin d'imprégner le flux avec les paramètres corrects. Voir Patrick Réponse ci-dessous.


@Martin York Voir en Bold - Je n'utilise pas std :: Ostream Object ...


Peut-être que ceci comme une question C seulement?


peut-être pas. J'utilise C ++ Tout Ze Way, à l'exception de iostream .... :(


Et pourquoi ne pas utiliser iostream? Il n'interfère pas du tout avec Printf.


Je pense qu'il est possible de synchroniser Iostream avec Stdio. J'ai oublié comment.


6 Réponses :


7
votes

La manière facile peut être de se convertir en un double juste avant la sortie et d'utiliser% E qui les imprimera dans une notation scientifique exponentielle. Essayez ceci: xxx


1 commentaires

+1 pour moi. Ce serait le moyen le plus simple de les voir. La seule chose que j'ajouterais est de définir un point de rupture. Tout ce qui est inférieur au point de rupture, vous devriez formater comme un numéro régulier.



9
votes

Vous pouvez utiliser Humanize_Number () qui utilise des suffixes comme K, M, etc., pour laisser des chiffres à faible commande. Ce n'est pas une routine standard, vous devriez donc d / l la source que j'ai liée à. (Licence 2-Clause BSD, autorise tout type d'utilisation.)

Humanize_Number Homme Page . P>

Humanize_Number Code source de Netbsd . P>

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


3 commentaires

C'est probablement mieux. Mon petit truc ne fonctionne que je suppose que si vous êtes assez bizarre pour envisager une notation scientifique "humaine lisible". ;)


Un très mineur QuiBble: "Préfixes" Allez avant les choses (c'est ce que "avant" signifie). "Les suffixes" vont après les choses. 110K utilise un suffixe K pour signifier 110 000.


Juste pour ajouter que ceci est une fonction juste pour les entiers - ne gère pas les numéros de points flottants ...



6
votes
std::cout.imbue( std::locale( "" ) );
std::cout << 100363443 << std::endl;

2 commentaires

Ouais. L'utilisation de la section locale est la manière constante de le faire.


Bonne idée, mais vous devriez être lazier: STD :: COUT.IMBUE (STD :: locale ("")); STD :: COUT << 123456789 << STD :: endl; Les paramètres régionaux sans nom utilisent les paramètres régionaux que l'utilisateur a configuré, donc (par exemple) un utilisateur avec leur ordinateur configuré pour les conventions américaines obtiendrait: 123 456 789 mais une utilisation des conventions allemandes obtiendrait: 123.456.789 et ainsi de suite. Dans certaines localités (par exemple, l'Inde, IIRC), vous ne voyez même pas normalement des groupes de trois - c'est quelque chose comme les cinq premiers chiffres (les moins importants) en tant que groupe, puis en groupes de deux à partir de là. Dans C, recherchez localeconv; C'est mieux que rien.



3
votes

N'oubliez pas la localisation (surtout que vous écrivez une bibliothèque).
En Europe (à l'exception du Royaume-Uni), il s'agirait de 1.000.000 plutôt que 1 000 000


0 commentaires

12
votes

Utilisez le drapeau non standard Apostrophe code> de la chaîne de format PrintF, si vous avez cette option disponible et que vous ne vous dérangerez pas de perdre un peu de portabilité.

Selon ma documentation, le ' code> drapeau est disponible pour Posix Systems depuis 1997. P>

Si vous êtes sur UNIX, Linux, Mac, ... vous ne devriez pas avoir de problème
Si vous êtes sur Windows, DOS, ISERIES, Android, ... Tous les paris sont désactivés (mais vous pouvez peut-être installer une couche de POSIX à votre système). P>

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


6 commentaires

C'est la seule réponse qui fait exactement ce que veut Andrei, en utilisant exactement les outils qu'il souhaite utiliser.


Je reçois un avertissement - Avertissement # 269: Conversion de chaîne de format non valide: printf ("\ n \ t% '12ld \ n", total);


@Andrei: Désolé pour ça. Apparemment, vous devez imprimer sur une chaîne, format de la chaîne et enfin de la chaîne formatée.


Je voulais dire que la nouvelle chaîne formatée comme quelque chose comme une lance se précipite.


@Andrei - Vous obtenez probablement l'avertissement car le modificateur Apostophe n'est pas standard. Par exemple, MSVC ne le supporte pas. Votre compilateur vous donne un bon rappel, même si la bibliothèque que vous utilisez, le supitptez-le.


@MiCHAE - c'est ce que je pensais, fils.



1
votes

Voici un exemple que j'ai écrit en droit C W / o à l'aide de la locale. Ne fonctionne que pour les positifs. (Beaucoup d'aide 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(12345678901234567890ull);
    printf("output %s\n", formatted);
    // output 12,345,678,901,234,567,890

}


0 commentaires