Created
February 20, 2012 18:44
-
-
Save cslarsen/1870641 to your computer and use it in GitHub Desktop.
Convert big number to human readable format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* A simple way to format numbers as human readable strings. | |
* E.g., 123456789 ==> 123 million | |
* | |
* Written by Christian Stigen Larsen | |
* http://csl.sublevel3.org | |
* | |
* Placed in the public domain by the author, 2012 | |
*/ | |
#include <stdio.h> | |
#include <math.h> | |
#include <string.h> | |
/* | |
* Short scale units | |
* http://en.wikipedia.org/wiki/Short_scale | |
*/ | |
static const char* short_scale[] = { | |
"", | |
"thousand", | |
"million", | |
"billion", | |
"trillion", | |
"quadrillion", | |
"quintillion", | |
"sextillion", | |
"septillion" | |
}; | |
/* | |
* Long scale units | |
* http://en.wikipedia.org/wiki/Short_scale | |
*/ | |
static const char* long_scale[] = { | |
"", | |
"thousand", | |
"million", | |
"milliard", | |
"billion", | |
"billiard", | |
"trillion", | |
"trilliard", | |
"quadrillion" | |
}; | |
/* | |
* Convert number to human readable string using | |
* the given naming system. | |
*/ | |
const char* scale(double n, int decimals = 1, const char* units[] = short_scale) | |
{ | |
/* | |
* Number of digits in n is given by | |
* 10^x = n ==> x = log(n)/log(10) = log_10(n). | |
* | |
* So 1000 would be 1 + floor(log_10(10^3)) = 4 digits. | |
*/ | |
int digits = n==0? 0 : 1+floor(log10l(fabs(n))); | |
// determine base 10 exponential | |
int exp = digits <= 4? 0 : 3*((digits-1)/3); | |
// normalized number | |
double m = n / powl(10, exp); | |
// no decimals? then don't print any | |
if ( m - static_cast<long>(n) == 0 ) | |
decimals = 0; | |
// don't print unit for exp<3 | |
static char s[32]; | |
static const char* fmt[] = {"%1.*lf %s", "%1.*lf"}; | |
sprintf(s, fmt[exp<3], decimals, m, units[exp/3]); | |
return s; | |
} | |
/* | |
* Convert number to short scale representation | |
*/ | |
const char* sscale(double n, int decimals = 1) | |
{ | |
static char s[32]; | |
strcpy(s, scale(n, decimals, short_scale)); | |
return s; | |
} | |
/* | |
* Convert number to long scale representation | |
*/ | |
const char* lscale(double n, int decimals = 1) | |
{ | |
static char s[32]; | |
strcpy(s, scale(n, decimals, long_scale)); | |
return s; | |
} | |
void test(double n) | |
{ | |
printf("%.lf in short scale is %s and %s in long scale\n", n, sscale(n), lscale(n)); | |
} | |
int main() | |
{ | |
long numbers[] = { | |
1000000000, | |
0, | |
1, | |
12, | |
123, | |
1234, | |
12345, | |
123456, | |
1234567, | |
12345678, | |
123456789, | |
1234567890, | |
12345678901, | |
123456789012, | |
1234567890123, | |
12345678901234, | |
123456789012345, | |
1234567890123456, | |
12345678901234567, | |
123456789012345677, | |
1234567890123456789 | |
}; | |
for ( size_t n=0; n<sizeof(numbers)/sizeof(long); ++n ) | |
test(numbers[n]); | |
test(-1); | |
test((double)12345.6789); | |
test((double)123456789012345678910.223); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Compiling and running the code produces the following output: