convert astronomically large numbers into human re

2020-02-09 04:46发布

My program prints out HUGE numbers - like 100363443, up to a trillion -- and it sort of hard to read them, so I would like to print any number in easy to read form.

right now I use

printf ("%10ld", number);

format

I would appreciate a resulting number using printf. Most of my code is c++ yet I don't want to introduce std::cout, as I already have printf

thanks

6条回答
淡お忘
2楼-- · 2020-02-09 04:58

Easy way might be to convert to a double just before output and use %e which will print them in exponential scientific notation. Try this:

double n = (double)number;
printf("%10.0e", n);
查看更多
何必那么认真
3楼-- · 2020-02-09 05:00

Here is an example I wrote in straight C w/o using locale. Only works for positives. (Much help from "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

}
查看更多
Anthone
4楼-- · 2020-02-09 05:03

Use the non-standard apostrophe flag in the printf format string, if you have that option available and don't mind losing a little bit of portability.

According to my documentation, the ' flag is available for POSIX systems since 1997.

If you are on Unix, Linux, Mac, ... you should have no problem
If you are on Windows, DOS, iSeries, Android, ... all bets are off (but maybe you can install a POSIX layer to your system).

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

On my system this program produces:

# %'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
查看更多
我命由我不由天
5楼-- · 2020-02-09 05:10

Remember localization (especiallyif you are writing a library).
In europe (except the UK) it would be 1.000.000 rather than 1,000,000

查看更多
虎瘦雄心在
6楼-- · 2020-02-09 05:15
std::cout << std::setprecision(5) << std::scientific << 100363443.0;

note that the number is a float

EDIT: or if you don't like scientific I found this on the net:

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: As pointed out by Jerry you don't need the comma class as above, this seems sufficient by itself (although there are presumably locales which don't format large numbers at all?):

std::cout.imbue( std::locale( "" ) );
std::cout << 100363443 << std::endl;
查看更多
一纸荒年 Trace。
7楼-- · 2020-02-09 05:19

You could use humanize_number() which uses suffixes like k, m, etc., to leave out low order digits. This is not a standard routine, so you should d/l the source I have linked to. (2-clause BSD license, allows any kind of use.)

Humanize_number man page.

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

This works by appending suffixes as follows:

       Suffix    Description    Multiplier
       k         kilo           1024
       M         mega           1048576
       G         giga           1073741824
       T         tera           1099511627776
       P         peta           1125899906842624
       E         exa            1152921504606846976
查看更多
登录 后发表回答