Reputation: 381
How would you create a function (in PHP) to return a value for the appropriate rounded ranking group (e.g. "Top 5", "Top 10", "Top 15", ... "Top 1 million", "Top 5 million", "Top 10 million", "Top 15 million").
Note that it should round up to the nearest 1, 5 or 10 - e.g. "Top 15 million" rather than "Top 12 million".
Example:
Rank = Output
This should work all the way up to trillions.
My current function works (sort of) however it would return a value for a ranking group of top 15 as top 20 instead.
private function format_number_iollions($amount,$style=null) {
$amount = (0 + str_replace(',', '', $amount));
if (!is_numeric($amount)){
return false;
}
$plusString = '';
switch ($style){
case 'plus':
$plusString = '+';
break;
}
if ($style==='rank' && $amount<=10){
return 10;
}
// filter and format it
if ($amount>1000000000000){
if ($style==='rank'){
$v = ceil(($amount/1000000000000));
} else {
$v = floor(($amount/1000000000000));
}
$v .= $plusString.' trillion';
} else if ($amount>1000000000){
if ($style==='rank'){
$v = ceil(($amount/1000000000));
} else {
$v = floor(($amount/1000000000));
}
$v .= $plusString.' billion';
} else if ($amount>1000000){
if ($style==='rank'){
$v = ceil(($amount/1000000));
} else {
$v = floor(($amount/1000000));
}
$v .= $plusString.' million';
} else if ($amount>100000){
if ($style==='rank'){
$v = ceil(($amount/100000));
} else {
$v = floor(($amount/100000));
}
$v .= '00,000'.$plusString;
} else if ($amount>10000){
if ($style==='rank'){
$v = ceil(($amount/10000));
} else {
$v = floor(($amount/10000));
}
$v .= '0,000'.$plusString;
} else if ($amount>1000){
if ($style==='rank'){
$v = ceil(($amount/1000));
} else {
$v = floor(($amount/1000));
}
$v .= ',000'.$plusString;
} else if ($amount>100){
if ($style==='rank'){
$v = ceil(($amount/100));
} else {
$v = floor(($amount/100));
}
$v .= '00'.$plusString;
} else if ($amount>10){
if ($style==='rank'){
$v = ceil(($amount/10));
} else {
$v = floor(($amount/10));
}
$v .= '0'.$plusString;
} else {
return number_format($amount);
}
return $v;
}
UPDATE - the final solution is this function (if anyone needs it):
private function get_rank_group($rawrank) {
// Divide by 1000 and count how many divisions were done
$rank_scale = 0;
while ($rawrank >= 1000) {
$rawrank /= 1000;
$rank_scale++;
}
// Determine which Top X can be
if ($rawrank >= 100) {
$lim_name = (floor(($rawrank-1) / 50) + 1) * 50;
} else {
$lim_name = (floor(($rawrank-1) / 5) + 1) * 5;
}
// if its in the next higher level
if ($lim_name >= 1000) {
$lim_name = '1';
$rank_scale++;
}
static $rank_scale_names = array('', ',000', ' Million', ' Billion', ' Trillion', ' Quadrillion', ' Quintillion', ' Sextillion', ' Septillion');
if (!isset($rank_scale_names[$rank_scale])){
return null; //too much - add higher word-numbers to $rank_scale_names
} else {
return "$lim_name{$rank_scale_names[$rank_scale]}";
}
}
Upvotes: 0
Views: 131
Reputation: 4914
As an improvement of AterLux's Solution
...
// Determine which Top X can be
if ($rawrank >= 100) {
$lim_name = (floor(($rawrank-1) / 50) + 1) * 50;
} else {
$lim_name = (floor(($rawrank-1) / 5) + 1) * 5;
}
// if its in the next higher level
if ($lim_name >= 1000) {
$lim_name = '1';
$rank_scale++;
}
static $rank_scale_names = array( ...
Output
1 -> Top 5
5 -> Top 5
9 -> Top 10
10 -> Top 10
12 -> Top 15
16 -> Top 20
49 -> Top 50
50 -> Top 50
51 -> Top 55
299 -> Top 300
300 -> Top 300
301 -> Top 350
995 -> Top 1 Thousand
12345 -> Top 15 Thousand
654321 -> Top 700 Thousand
234567890 -> Top 250 Million
1234567890123456789 -> Top 5 Quintillion
Upvotes: 1
Reputation: 4654
<?php
function get_rank_group($rawrank) {
// Divide by 1000 and count how many divisions were done
$rank_scale = 0;
while ($rawrank >= 1000) {
$rawrank /= 1000;
$rank_scale++;
}
// Determine which Top X can be
static $rank_split = array(3, 5, 10, 15, 20, 30, 50, 100, 150, 200, 300, 500);
$lim_name = false;
// Look for a group, which is not less than the number
foreach ($rank_split as $lim) {
if ($rawrank <= $lim) {
$lim_name = $lim;
break;
}
}
// If nothing was found then it is a Top 1 of (next scaler) eg. 501 is Top 1 Thousand
if ($lim_name === false) {
$lim_name = '1';
$rank_scale++;
}
static $rank_scale_names = array('', ' Thousand', ' Million', ' Billion', ' Trillion', ' Quadrillion', ' Quintillion', ' Sextillion', ' Septillion'); // etc
if (!isset($rank_scale_names[$rank_scale])) return 'too much!'; // just check
return "Top $lim_name{$rank_scale_names[$rank_scale]}";
}
// Tests
$tests = array(1, 2, 3, 4, 16, 49, 50, 51, 299, 300, 301, 12345, 654321, 234567890, 1234567890123456789);
foreach ($tests as $test) {
print ("$test -> " . get_rank_group($test) . PHP_EOL);
}
The output:
1 -> Top 3
2 -> Top 3
3 -> Top 3
4 -> Top 5
16 -> Top 20
49 -> Top 50
50 -> Top 50
51 -> Top 100
299 -> Top 300
300 -> Top 300
301 -> Top 500
12345 -> Top 15 Thousand
654321 -> Top 1 Million
234567890 -> Top 300 Million
1234567890123456789 -> Top 3 Quintillion
Upvotes: 2