Shorten long numbers to K/M/B?

2020-01-24 20:48发布

I've googled this a lot but i can't find any helpful functions based on my queries.

What i want is:

100 -> 100
1000 -> 1,000
142840 -> 142,840

BUT

2023150 -> 2.023M ( i still want 3 additional numbers for more accuracy )
5430120215 -> 5.430B

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

Thanks!

9条回答
虎瘦雄心在
2楼-- · 2020-01-24 20:58
function number_abbr($number)
{
    $abbrevs = [12 => 'T', 9 => 'B', 6 => 'M', 3 => 'K', 0 => ''];

    foreach ($abbrevs as $exponent => $abbrev) {
        if (abs($number) >= pow(10, $exponent)) {
            $display = $number / pow(10, $exponent);
            $decimals = ($exponent >= 3 && round($display) < 100) ? 1 : 0;
            $number = number_format($display, $decimals).$abbrev;
            break;
        }
    }

    return $number;
}

Works for positives and negatives.

查看更多
太酷不给撩
3楼-- · 2020-01-24 21:01

Try this. Accounts for the groups k, M, B, T, and Q (quadrillion). Anything higher than 999Q shows as 999Q+.

function number($num, $precision = 2)
{
    $absNum = abs($num);

    if ($absNum < 1000)
    {
        return (string)round($num, $precision);
    }

    $groups = ['k','M','B','T','Q'];

    foreach ($groups as $i => $group)
    {
        $div = 1000 ** ($i + 1);

        if ($absNum < $div * 1000)
        {
            return round($num / $div, $precision) . $group;
        }
    }

    return '999Q+';
}
查看更多
forever°为你锁心
4楼-- · 2020-01-24 21:06

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;
}
查看更多
家丑人穷心不美
5楼-- · 2020-01-24 21:10
<?php
// Converts a number into a short version, eg: 1000 -> 1k
// Based on: http://stackoverflow.com/a/4371114
function number_format_short( $n, $precision = 1 ) {
    if ($n < 900) {
        // 0 - 900
        $n_format = number_format($n, $precision);
        $suffix = '';
    } else if ($n < 900000) {
        // 0.9k-850k
        $n_format = number_format($n / 1000, $precision);
        $suffix = 'K';
    } else if ($n < 900000000) {
        // 0.9m-850m
        $n_format = number_format($n / 1000000, $precision);
        $suffix = 'M';
    } else if ($n < 900000000000) {
        // 0.9b-850b
        $n_format = number_format($n / 1000000000, $precision);
        $suffix = 'B';
    } else {
        // 0.9t+
        $n_format = number_format($n / 1000000000000, $precision);
        $suffix = 'T';
    }
  // Remove unecessary zeroes after decimal. "1.0" -> "1"; "1.00" -> "1"
  // Intentionally does not affect partials, eg "1.50" -> "1.50"
    if ( $precision > 0 ) {
        $dotzero = '.' . str_repeat( '0', $precision );
        $n_format = str_replace( $dotzero, '', $n_format );
    }
    return $n_format . $suffix;
}
/*
Example Usage:
number_format_short(7201); // Output: 7.2k
Demo:
echo '<table>';
for($d = 0; $d < 16; $d++ ) {
    $n = intval("09" . str_repeat( "0", $d ));
    $n = $n / 10;
    echo number_format_short($n) .'<br>'; // 0.9
    $n = intval("1" . str_repeat( "0", $d ));
    echo number_format_short($n) .'<br>'; // 1.0
    $n = intval("11" . str_repeat( "0", $d ));;
    $n = $n / 10;
    echo number_format_short($n) .'<br>'; // 1.1
}
echo '</table>';
Demo Output:
0.9
1
1.1

9
10
11

90
100
110

0.9K
1K
1.1K

9K
10K
11K

90K
100K
110K

0.9M
1M
1.1M

9M
10M
11M

90M
100M
110M

0.9B
1B
1.1B

9B
10B
11B

90B
100B
110B

0.9T
1T
1.1T

9T
10T
11T

90T
100T
110T

900T
1,000T
1,100T
*/
查看更多
一纸荒年 Trace。
6楼-- · 2020-01-24 21:12

Altough this question was asked quite some time ago I have a different solution, which I think is even more simple:

function shorten($number){
    $suffix = ["", "K", "M", "B"];
    $precision = 1;
    for($i = 0; $i < count($suffix); $i++){
        $divide = $number / pow(1000, $i);
        if($divide < 1000){
            return round($divide, $precision).$suffix[$i];
            break;
        }
    }
}
echo shorten(1000);

I hope that it's still helpful for someone.

查看更多
看我几分像从前
7楼-- · 2020-01-24 21:13

CakePHP has a Number Helper with a method toReadableSize. You should be able to grok it and come up with something on your own. In it, $this->precision is basically like number_format(), and __n is a singular-or-plural function.

查看更多
登录 后发表回答