Skip to content

Instantly share code, notes, and snippets.

@fidelisrafael
Forked from cslarsen/human-numbers.cpp
Created February 1, 2018 18:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fidelisrafael/678663e0f5a6dd3e85a68a3370132e00 to your computer and use it in GitHub Desktop.
Save fidelisrafael/678663e0f5a6dd3e85a68a3370132e00 to your computer and use it in GitHub Desktop.
Convert big number to human readable format
/*
* 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