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
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
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
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);
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;
Remember localization (especiallyif you are writing a library).
In europe (except the UK) it would be 1.000.000 rather than 1,000,000
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
}