开发者

Shorten long numbers to K/M/B?

开发者 https://www.devze.com 2023-01-28 23:10 出处:网络
I\'ve googled this a lot but i can\'t find any helpful functions based on my queries. What i want is: 100 -> 100

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.开发者_如何学Python430B

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


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;
}


I took the answer BoltClock provided and tweaked it a bit with ease of configuration in mind.

// Shortens a number and attaches K, M, B, etc. accordingly
function number_shorten($number, $precision = 3, $divisors = null) {

    // Setup default $divisors if not provided
    if (!isset($divisors)) {
        $divisors = array(
            pow(1000, 0) => '', // 1000^0 == 1
            pow(1000, 1) => 'K', // Thousand
            pow(1000, 2) => 'M', // Million
            pow(1000, 3) => 'B', // Billion
            pow(1000, 4) => 'T', // Trillion
            pow(1000, 5) => 'Qa', // Quadrillion
            pow(1000, 6) => 'Qi', // Quintillion
        );    
    }

    // Loop through each $divisor and find the
    // lowest amount that matches
    foreach ($divisors as $divisor => $shorthand) {
        if (abs($number) < ($divisor * 1000)) {
            // We found a match!
            break;
        }
    }

    // We found our match, or there were no matches.
    // Either way, use the last defined value for $divisor.
    return number_format($number / $divisor, $precision) . $shorthand;
}


<?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
*/


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.


Try this

function custom_number_format($n, $precision = 1) {
        if ($n < 900) {
        // Default
         $n_format = number_format($n);
        } else if ($n < 900000) {
        // Thausand
        $n_format = number_format($n / 1000, $precision). 'K';
        } else if ($n < 900000000) {
        // Million
        $n_format = number_format($n / 1000000, $precision). 'M';
        } else if ($n < 900000000000) {
        // Billion
        $n_format = number_format($n / 1000000000, $precision). 'B';
        } else {
        // Trillion
        $n_format = number_format($n / 1000000000000, $precision). 'T';
    }
    return $n_format;
    }


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.


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

function number(float $num, int $precision = 2): string
{
    $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+';
}


I took a different approach based on the previous solutions. Basically it uses the log() function to get rid of the for statement:

function number_shorten($number, $precision = 3)
{
    $suffixes = ['', 'K', 'M', 'B', 'T', 'Qa', 'Qi'];
    $index = (int) log(abs($number), 1000);
    $index = max(0, min(count($suffixes) - 1, $index)); // Clamps to a valid suffixes' index
    return number_format($number / 1000 ** $index, $precision) . $suffixes[$index];
}

It works for positive and negative numbers.


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.


You can try this

 function number_formation($number, $precision = 3) {
        if ($number < 1000000) {

            $formatted_number = number_format($number); /* less than a million */
        } else if ($number < 1000000000) {

            $formatted_number = number_format($number / 1000000, $precision) . 'M'; /* billion */
        } else {

            $formatted_number = number_format($number  / 1000000000, $precision) . 'B'; /* for billion */
        }

        return $formatted_number;
    }


Some Modify
$precision = 1, 2, 3 or 4 ...

function kmb($count, $precision = 2) {
if ($count < 1000000) {
// Anything less than a million
$n_format = number_format($count / 1000) . 'K';
} else if ($count < 1000000000) {
// Anything less than a billion
$n_format = number_format($count / 1000000, $precision) . 'M';
} else {
// At least a billion
$n_format = number_format($count / 1000000000, $precision) . 'B';
}
return $n_format;
}

echo kmb(272937);

273K

echo kmb(2729347);

2.73M

echo kmb(2729347874);

2.73B


I refactored the OG best answer to make it better and a function

public function formatNumber($number)
{
    if ($number < 1000000) {
        // Anything less than a million
        return number_format($number);
    } else if ($number < 1000000000) {
        // Anything less than a billion
        return number_format($number / 1000000, 0) . 'm';
    } else {
        // At least a billion
        return number_format($number / 1000000000, 0) . 'b';
    }
}


Here's a modified version that worked really well for my needs. This allows me to specify if I want 5,500,000 to appear as "5.5M" (short style) or "5.5 million" (long style).

function nice_number_format( $n, $style = 'short' ) {
    if ($n < 1000) {
        $n_format = number_format($n);
    } else if ($n < 1000000) {
        $n_format = floatval(number_format($n / 1000, 2));
        $suffix = ($style == 'long' ? ' thousand' : 'K');
    } else if ($n < 1000000000) {
        $n_format = floatval(number_format($n / 1000000, 2));
        $suffix = ($style == 'long' ? ' million' : 'M');
    } else {
        $n_format = floatval(number_format($n / 1000000000, 2));
        $suffix = ($style == 'long' ? ' billion' : 'B');
    } 
    return $n_format . $suffix;
}


Simply you can use this function:

function shortNumber($number = null)
{
    if($number == 0) {
        $short = 'No data';
    } elseif($number <= 999) {
        $short = $number;
    } elseif($number < 1000000) {
        $short = round($number/1000, 2).'K';
    } elseif($number < 1000000000) {
        $short =  round($number/1000000, 2).'M';
    } elseif($number >= 1000000000) {
        $short = round($number/1000000000, 2).'B';
    }

   return $short;
}

Method:

<?php 
 echo shortNumber(1000)
 // output = 1K
?>

Output

// Output = 1K  
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号