Сократить длинные числа до K/M/B?

Я много искал это, но не могу найти полезные функции, основанные на моих запросах.

Я хочу:

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

НО

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

Я бы полностью оценил любые пользовательские функции для динамического выбора предела, если это возможно.

Спасибо!

Ответ 1

Используйте 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';
}

Я бы полностью оценил любые пользовательские функции для динамического выбора предела, если это возможно.

Если "limit" относится к числу десятичных знаков (точности), это легко:

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

Ответ 2

Я принял ответ, предоставленный BoltClock, и немного изменил его с легкостью в конфигурации.

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

Ответ 3

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

Ответ 4

Попробуйте это

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

Ответ 5

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

Работает на позитивы и негативы.

Ответ 6

CakePHP имеет Number Helper с помощью метода toReadableSize. Вы должны быть в состоянии понять его и придумать что-то по своему усмотрению. В нем $this->precision в основном похож на number_format(), а __n - функция единственного числа или множественного числа.

Ответ 7

Вы можете попробовать это

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

Ответ 8

Хотя этот вопрос был задан довольно давно, у меня есть другое решение, которое я считаю еще более простым:

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

Я надеюсь, что это все еще полезно для кого-то.

Ответ 9

Попробуй это. Учитывает группы k, M, B, T и Q (квадриллион). Все, что выше 999Q, отображается как 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+';
}