Shorten Long Numbers to K/M/B

Shorten long numbers to K/M/B?

Use number_format():

if ($n < 1000000) {
// Anything less than a million
$n_format = number_format($n);
} else if ($n < 1000000000) {
// Anything less than a billion
$n_format = number_format($n / 1000000, 3) . 'M';
} else {
// At least a billion
$n_format = number_format($n / 1000000000, 3) . 'B';
}

I would totally appreciate any custom functions to dynamically choose the limit if possible.

If "limit" refers to the number of decimal places (the precision), that's easy:

function custom_number_format($n, $precision = 3) {
if ($n < 1000000) {
// Anything less than a million
$n_format = number_format($n);
} else if ($n < 1000000000) {
// Anything less than a billion
$n_format = number_format($n / 1000000, $precision) . 'M';
} else {
// At least a billion
$n_format = number_format($n / 1000000000, $precision) . 'B';
}

return $n_format;
}

Shorten long numbers to include K/M/B/T

Put in your config/locales/en.yml:

en:
number:
human:
decimal_units:
format: "%n%u"
units:
unit: ""
thousand: K
million: M
billion: B
trillion: T
quadrillion: Q

Then you'll get:

number_to_human 420 # => "420"
number_to_human 5680 # => "5.68K"
number_to_human 12680 # => "12.7K"
number_to_human 6802251 # => "6.8M"
number_to_human 894100158 # => "894M"

How to convert large number to shorten K/M/B in Dart

String toString(int value) {
const units = <int, String>{
1000000000: 'B',
1000000: 'M',
1000: 'K',
};
return units.entries
.map((e) => '${value ~/ e.key}${e.value}')
.firstWhere((e) => !e.startsWith('0'), orElse: () => '$value');
}

Convert long number into abbreviated string in JavaScript, with a special shortness requirement

I believe ninjagecko's solution doesn't quite conform with the standard you wanted. The following function does:

function intToString (value) {
var suffixes = ["", "k", "m", "b","t"];
var suffixNum = Math.floor((""+value).length/3);
var shortValue = parseFloat((suffixNum != 0 ? (value / Math.pow(1000,suffixNum)) : value).toPrecision(2));
if (shortValue % 1 != 0) {
shortValue = shortValue.toFixed(1);
}
return shortValue+suffixes[suffixNum];
}

For values greater than 99 trillion no letter will be added, which can be easily fixed by appending to the 'suffixes' array.

Edit by Philipp follows: With the following changes it fits with all requirements perfectly!

function abbreviateNumber(value) {
var newValue = value;
if (value >= 1000) {
var suffixes = ["", "k", "m", "b","t"];
var suffixNum = Math.floor( (""+value).length/3 );
var shortValue = '';
for (var precision = 2; precision >= 1; precision--) {
shortValue = parseFloat( (suffixNum != 0 ? (value / Math.pow(1000,suffixNum) ) : value).toPrecision(precision));
var dotLessShortValue = (shortValue + '').replace(/[^a-zA-Z 0-9]+/g,'');
if (dotLessShortValue.length <= 2) { break; }
}
if (shortValue % 1 != 0) shortValue = shortValue.toFixed(1);
newValue = shortValue+suffixes[suffixNum];
}
return newValue;
}

Format number to K/M/B within blade template

I don't know any blade functions that can do this. However, you can use the PHP Humanizer package for this. For example, from their documentation:

use Coduo\PHPHumanizer\NumberHumanizer;

NumberHumanizer::metricSuffix(-1); // "-1"
NumberHumanizer::metricSuffix(0); // "0"
NumberHumanizer::metricSuffix(1); // "1"
NumberHumanizer::metricSuffix(101); // "101"
NumberHumanizer::metricSuffix(1000); // "1k"
NumberHumanizer::metricSuffix(1240); // "1.2k"
NumberHumanizer::metricSuffix(1240000); // "1.24M"
NumberHumanizer::metricSuffix(3500000); // "3.5M"

The good thing about the package is, it also supports multiple locales.

Edit: There are also other alternative solutions as discussed here. This could be a better option for you if you just need to shorten numbers.

Shorten long numbers to include K/M/B/T

Put in your config/locales/en.yml:

en:
number:
human:
decimal_units:
format: "%n%u"
units:
unit: ""
thousand: K
million: M
billion: B
trillion: T
quadrillion: Q

Then you'll get:

number_to_human 420 # => "420"
number_to_human 5680 # => "5.68K"
number_to_human 12680 # => "12.7K"
number_to_human 6802251 # => "6.8M"
number_to_human 894100158 # => "894M"

Format a number as 2.5K if a thousand or more, otherwise 900

Sounds like this should work for you:

function kFormatter(num) {

return Math.abs(num) > 999 ? Math.sign(num)*((Math.abs(num)/1000).toFixed(1)) + 'k' : Math.sign(num)*Math.abs(num)

}



console.log(kFormatter(1200)); // 1.2k

console.log(kFormatter(-1200)); // -1.2k

console.log(kFormatter(900)); // 900

console.log(kFormatter(-900)); // -900

ultimate short custom number formatting - K, M, B, T, etc., Q, D, Googol

internal custom number formatting solution:

sadly, the internal formatting in google sheets is by default able to work with only 3 types of numbers:

  • positive (1, 2, 5, 10, ...)
  • negative (-3, -9, -7, ...)
  • zero (0)

this can be tweaked to show custom formatting like thousands K, millions M and regular small numbers:

[>999999]0.0,,"M";[>999]0.0,"K";0

or only thousands K, millions M, billions B

[<999950]0.0,"K";[<999950000]0.0,,"M";0.0,,,"B"

or only negative thousands K, negative millions M, negative billions B

[>-999950]0.0,"K";[>-999950000]0.0,,"M";0.0,,,"B"

or only millions M, billions B, trillions T:

[<999950000]0.0,,"M";[<999950000000]0.0,,,"B";0.0,,,,"T"

or only numbers from negative million M to positive million M:

[>=999950]0.0,,"M";[<=-999950]0.0,,"M";0.0,"K"

Sample Image

but you always got only 3 slots you can use, meaning that you can't have trillions as the 4th type/slot. fyi, the 4th slot exists, but it's reserved for text. to learn more about internal formatting in google sheets see:

  • https://developers.google.com/sheets/api/guides/formats#meta_instructions
  • https://www.benlcollins.com/spreadsheets/google-sheets-custom-number-format/






formula (array formula) solution:

the formula approach is more versatile... first, you will need to decide on the system/standard you want to use (American, European, Greek, International, Unofficial, etc...):

  • en.wikipedia.org/wiki/Names_of_large_numbers
  • en.wikipedia.org/wiki/Metric_prefix
  • simple.wikipedia.org/wiki/Names_for_large_numbers
  • home.kpn.nl/vanadovv/BignumbyN

after that try:

=INDEX(REGEXREPLACE(IFNA(TEXT(A:A/10^(VLOOKUP(LEN(TEXT(INT(ABS(A:A)), "0"))-1, 
SEQUENCE(35, 1,, 3), 1, 1)), "#.0")&VLOOKUP(ABS(A:A)*1, {{10^SEQUENCE(34, 1, 3, 3)},
{"K "; "M "; "B "; "T "; "Qa "; "Qi "; "Sx "; "Sp "; "O "; "N "; "D "; "Ud ";
"Dd "; "Td "; "Qad"; "Qid"; "Sxd"; "Spd"; "Od "; "Nd "; "V "; "Uv "; "Dv "; "Tv ";
"Qav"; "Qiv"; "Sxv"; "Spv"; "Ov "; "Nv "; "Tr "; "Ut "; "Dt "; "Tt "}}, 2, 1),
IF(ISBLANK(A:A),, TEXT(A:A, "0.0 "))), "^0\.0 $", "0 "))
  • works with positive numbers
  • works with negative numbers
  • works with zero
  • works with decimal numbers
  • works with numeric values
  • works with plain text numbers
  • works with scientific notations
  • works with blank cells
  • works up to googol 10^104 in both ways

Sample Image




extra points if you are interested in how it works...

let's start with virtual array {{},{}}. SEQUENCE(34, 1, 3, 3) will give us 34 numbers in 1 column starting from number 3 with the step of 3 numbers:

Sample Image

these will be used as exponents while rising 10 on the power ^

Sample Image

so our virtual array will be:

Sample Image

next, we insert it as the 2nd argument of VLOOKUP where we check ABS absolute values (converting negative values into positive) of A column multiplied by *1 just in case values of A column are not numeric. via VLOOKUP we return the second 2 column and as the 4th argument, we use approximate mode 1

Sample Image

numbers from -999 to 999 will intentionally error out at this point so we could later use IFNA to "fix" our errors with IF(A:A=IF(,,),, TEXT(A:A, "#.0 ")) translated as: if range A:A is truly empty ISBLANK output nothing, else format A column with provided pattern #.0 eg. if cell A5 = empty, the output will be blank cell... if -999 < A5=50 < 999 the output will be 50.0

Sample Image

and the last part:

TEXT(A:A/10^(VLOOKUP(LEN(TEXT(INT(ABS(A:A)), "0"))-1, 
SEQUENCE(35, 1,, 3), 1, 1)), "#.0")

ABS(A:A) to convert negative numbers into positive. INT to remove decimal numbers if any. TEXT(, "0") to convert scientific notations 3E+8 into regular numbers 300000000. LEN to count digits. -1 to correct for base10 notation. VLOOKUP above-constructed number in SEQUENCE of 35 numbers in 1 column, this time starting from number 0 ,, with the step of 3 numbers. return via VLOOKUP the first 1 column (eg. the sequence) in approximate mode 1 of vlookup. insert this number as exponent when rising the 10 on power ^. and take values in A column and divide it by the above-constructed number 10 raised on the power ^ of a specific exponent. and lastly, format it with TEXT as #.0

Sample Image

to convert ugly 0.0 into beautiful 0 we just use REGEXREPLACE. and INDEX is used instead of the longer ARRAYFORMULA.

sidenote: to remove trailing spaces (which are there to add nice alignment lol) either remove them from the formula or use TRIM right after INDEX.







script solution:

eternal gratitude to @TheMaster for covering this

here is a mod of it:

/**
* formats various numbers according to the provided short format
* @customfunction
* @param {A1:C100} range a 2D array
* @param {[X1:Y10]} database [optional] a real/virtual 2D array
* where the odd column holds exponent of base 10
* and the even column contains format suffixes
* @param {[5]} value [optional] fix suffix to fixed length
* by padding spaces (only if the second parameter exists)
*/
// examples:
// =CSF(A1:A)
// =CSF(2:2; X5:Y10)
// =CSF(A1:3; G10:J30)
// =CSF(C:C; X:Y; 2) to use custom alignment
// =CSF(C:C; X:Y; 0) to remove alignment
// =INDEX(TRIM(CSF(A:A))) to remove alignment
// =CSF(B10:D30; {3\ "K"; 4\ "TK"}) for non-english sheets
// =CSF(E5, {2, "deci"; 3, "kilo"}) for english sheets
// =INDEX(IF(ISERR(A:A*1); A:A; CSF(A:A))) to return non-numbers
// =INDEX(IF((ISERR(A:A*1))+(ISBLANK(A:A)), A:A, CSF(A:A*1))) enforce mode
function CSF(
range,
database = [
[3, 'K' ], //Thousand
[6, 'M' ], //Million
[9, 'B' ], //Billion
[12, 'T' ], //Trillion
[15, 'Qa' ], //Quadrillion
[18, 'Qi' ], //Quintillion
[21, 'Sx' ], //Sextillion
[24, 'Sp' ], //Septillion
[27, 'O' ], //Octillion
[30, 'N' ], //Nonillion
[33, 'D' ], //Decillion
[36, 'Ud' ], //Undecillion
[39, 'Dd' ], //Duodecillion
[42, 'Td' ], //Tredecillion
[45, 'Qad'], //Quattuordecillion
[48, 'Qid'], //Quindecillion
[51, 'Sxd'], //Sexdecillion
[54, 'Spd'], //Septendecillion
[57, 'Od' ], //Octodecillion
[60, 'Nd' ], //Novemdecillion
[63, 'V' ], //Vigintillion
[66, 'Uv' ], //Unvigintillion
[69, 'Dv' ], //Duovigintillion
[72, 'Tv' ], //Trevigintillion
[75, 'Qav'], //Quattuorvigintillion
[78, 'Qiv'], //Quinvigintillion
[81, 'Sxv'], //Sexvigintillion
[84, 'Spv'], //Septenvigintillion
[87, 'Ov' ], //Octovigintillion
[90, 'Nv' ], //Novemvigintillion
[93, 'Tr' ], //Trigintillion
[96, 'Ut' ], //Untrigintillion
[99, 'Dt' ], //Duotrigintillion
[100, 'G' ], //Googol
[102, 'Tt' ], //Tretrigintillion or One Hundred Googol
],
value = 3
) {
if (
database[database.length - 1] &&
database[database.length - 1][0] !== 0
) {
database = database.reverse();
database.push([0, '']);
}
const addSuffix = num => {
const pad3 = (str = '') => str.padEnd(value, ' ');
const decim = 1 // round to decimal places
const separ = 0 // separate number and suffix
const anum = Math.abs(num);
if (num === 0)
return '0' + ' ' + ' '.repeat(separ) + ' '.repeat(decim) + pad3();
if (anum > 0 && anum < 1)
return String(num.toFixed(decim)) + ' '.repeat(separ) + pad3();
for (const [exp, suffix] of database) {
if (anum >= Math.pow(10, exp))
return `${(num / Math.pow(10, exp)).toFixed(decim)
}${' '.repeat(separ) + pad3(suffix)}`;
}
};
return customFunctionRecurse_(
range, CSF, addSuffix, database, value, true
);
}
function customFunctionRecurse_(
array, mainFunc, subFunc, ...extraArgToMainFunc
) {
if (Array.isArray(array))
return array.map(e => mainFunc(e, ...extraArgToMainFunc));
else return subFunc(array);
}

Sample Image

sidenote 1: this script does not need to be authorized priorly to usage

sidenote 2: cell formatting needs to be set to Automatic or Number otherwise use enforce mode







extra:

  • convert numbers into plain text strings/words
  • convert array of numbers into plain text strings/words
  • convert custom formatted numbers into numeric numbers/values
  • convert text string datetime into duration value
  • convert text string formatted numbers into duration

How to go about formatting 1200 to 1.2k in java

Here is a solution that works for any long value and that I find quite readable (the core logic is done in the bottom three lines of the format method).

It leverages TreeMap to find the appropriate suffix. It is surprisingly more efficient than a previous solution I wrote that was using arrays and was more difficult to read.

private static final NavigableMap<Long, String> suffixes = new TreeMap<> ();
static {
suffixes.put(1_000L, "k");
suffixes.put(1_000_000L, "M");
suffixes.put(1_000_000_000L, "G");
suffixes.put(1_000_000_000_000L, "T");
suffixes.put(1_000_000_000_000_000L, "P");
suffixes.put(1_000_000_000_000_000_000L, "E");
}

public static String format(long value) {
//Long.MIN_VALUE == -Long.MIN_VALUE so we need an adjustment here
if (value == Long.MIN_VALUE) return format(Long.MIN_VALUE + 1);
if (value < 0) return "-" + format(-value);
if (value < 1000) return Long.toString(value); //deal with easy case

Entry<Long, String> e = suffixes.floorEntry(value);
Long divideBy = e.getKey();
String suffix = e.getValue();

long truncated = value / (divideBy / 10); //the number part of the output times 10
boolean hasDecimal = truncated < 100 && (truncated / 10d) != (truncated / 10);
return hasDecimal ? (truncated / 10d) + suffix : (truncated / 10) + suffix;
}


Test code

public static void main(String args[]) {
long[] numbers = {0, 5, 999, 1_000, -5_821, 10_500, -101_800, 2_000_000, -7_800_000, 92_150_000, 123_200_000, 9_999_999, 999_999_999_999_999_999L, 1_230_000_000_000_000L, Long.MIN_VALUE, Long.MAX_VALUE};
String[] expected = {"0", "5", "999", "1k", "-5.8k", "10k", "-101k", "2M", "-7.8M", "92M", "123M", "9.9M", "999P", "1.2P", "-9.2E", "9.2E"};
for (int i = 0; i < numbers.length; i++) {
long n = numbers[i];
String formatted = format(n);
System.out.println(n + " => " + formatted);
if (!formatted.equals(expected[i])) throw new AssertionError("Expected: " + expected[i] + " but found: " + formatted);
}
}

How to go about formatting 1200 to 1.2k in Android studio

This should do the trick

String numberString = "";
if (Math.abs(number / 1000000) > 1) {
numberString = (number / 1000000).toString() + "m";

} else if (Math.abs(number / 1000) > 1) {
numberString = (number / 1000).toString() + "k";

} else {
numberString = number.toString();

}


Related Topics



Leave a reply



Submit