I'd like to convert currency values like this:
4 000 000 000 => 4b
2 000 000 => 2m
2 250 000 => 2.25m
195 000 => 195k
10 000 => 10k
Anyone know of an existing library/function that does this, or do I need to write this myself by means of conditionals that cater for 0-9999, 10000-999999, and so on..?
You can create a custom function for this. The below one, firstly removes everything but numbers from string. Then it formats the number according how big is it and to the digit provided.
function shorten($num, $digits = 1) {
$num = preg_replace('/[^0-9]/','',$num);
if ($num >= 1000000000) {
$num = number_format(($num / 1000000000), $digits, '.', '') + 0;
$num = $num . "b";
}
if ($num >= 1000000) {
$num = number_format(($num / 1000000), $digits, '.', '') + 0;
$num = $num . 'm';
}
if ($num >= 1000) {
$num = number_format(($num / 1000), $digits, '.', '') + 0;
$num = $num . 'k';
}
return $num;
}
echo shorten("4 000 000 000");
echo shorten("3 200 000 000");
echo shorten("195 000");
Demo: http://codepad.org/K971MzVx
You can create a function like this to display shorten the values but it would miss the exact value
function shortifyCurrency($var){
$var=doubleval($var);
if($var>=1000000000){
$var=($var/1000000000)."b";
}else if($var>=1000000){
$var=($var/1000000)."m";
}else if($var>=1000){
$var=($var/1000)."k";
}
return $var;
}
//Output 4b
echo shortifyCurrency(4000000000);
Or you could use the following function to display more detailed information about the value
function shortifyCurrencyXtream($var){
$var=doubleval($var);
$print_str="";
if($var>=1000000000){
$print_str.=round($var/1000000000)."b";
$var=$var%1000000000;
}
if($var>=1000000){
if($print_str!="") $print_str.=" ";
$print_str.=round($var/1000000)."m";
$var=$var%1000000;
}
if($var>=1000){
if($print_str!="") $print_str.=" ";
$print_str.=($var/1000)."k";
}
return $print_str;
}
//Output 4b 101m 500.3k
echo shortifyCurrencyXtream(4100500300);
Related
In Excel, column names are characters from A to Z, if there are more columns needed, it continues with AA, AB ...
I want to write a function, that converts integers to those excel column names.
0 .... A
25 ... Z
26 ... AA
702 ... AAA
.
.
.
The solution I came up with is working up to AZ, but I want it to work further.
function indexToXlxsColumn($index, $prefix="")
{
if($index < 26)
{
return $prefix.chr($index+65);
}else{
return indexToXlxsColumn($index % 26, "A");
}
}
How to adapt this function to work for every index without producing spaghetti code?
Here is the probleme
return indexToXlxsColumn($index % 26, "A");
You away set the next floor prefix to A , what happends when u have
input = 53 , the resultat should be "BB"
Code on paper
function indexToXlxsColumn($index, $prefix="")
{
if($index < 26) // 53 isnt less then 26
// second loop , 1 is less then 26
{
return $prefix.chr($index+65);
// $prefix = A
// chr($index+65) = B
// return "A"."B" ;
}else{
return indexToXlxsColumn($index % 26, "A");
// indexToXlxsColumn(53 % 26, "A") -> (1, "A")
}
}
---UPDATE---
Follow the ask here is the answer
function indexToXlxsColumn($index, $suffix ="")
{
if($index < 26){
return chr($index+65).$suffix ;
}
return indexToXlxsColumn(($index - $index%26)/26-1, chr($index%26+65).$suffix );
}
One of the implementations:
function indexToXlxsColumn($index)
{
$name = '';
while($index > 0) {
$mod = ($index - 1) % 26;
$name = chr(65 + $mod).$name;
$index = (int)(($index - $mod) / 26);
}
return $name;
}
// echo indexToXlxsColumn(26); // Z
echo indexToXlxsColumn(33); // AG
// echo indexToXlxsColumn(800); // ADT
I would do it a little differently. It bothered me to work with chr(). So I once stored the alphabet in a string and iterated over it until the index was successfully resolved.
max "zz"
<?php
function getIn($i) {
$str = 'abcdefghijklmnopqrstuvwxyz';
$r = (int) floor($i / 26) ;
$c = $i % 26;
return ($r) < 1 ? $str[$c] : $str[$r-1] . $str[$c];
}
echo getIn(52); // output: "ba"
Update with max "zzz"
function getIn($i) {
$str = 'abcdefghijklmnopqrstuvwxyz';
$r = (int) floor($i / 26);
$rr = $r >= 27 ? $r - 27 : null;
$c = $i % 26;
if ( $rr !== null) {
return $str[$c] : $str[$r-1] . $str[$c];
}
return ($r) < 1 ? $str[$c] : $str[$r-1] . $str[$c];
}
echo getIn(800); // ddu
echo getIn(1377); // zzz
PLACEHOLDER parts of the code return squiffy values! Needs review before using in the wild!!
In case anyone wants a utility function that does this, here's a python implementation:
n2AA performs the calculation from numeric to "AA" format.
def n2AA(n):
n=n-1
alphabet=["_"] + [chr(c+65) for c in range(0,26)]
w=len(alphabet)-1
accum=[]
for e in range(5,-1,-1):
expon=w**e
s=(n//expon)
r=n%expon
n=n-(s*expon)
if e>0:
accum.append(alphabet[s])
else:
accum.append(alphabet[s+1])
return "".join([a for a in accum if a != "_"])
And AA2n performs the inverse function, starting with "AA" format and returning the column number (starting at 1).
def AA2n(AA):
alphabet=["_"] + [chr(c+65) for c in range(0,26)]
w=len(alphabet)-1
accum=[]
for c in range(0,len(AA)):
expon=w**(len(AA)-1-c)
accum.append((alphabet.index(AA[c]))*expon)
return sum(accum)
I am creating a social site. And I want to show people things like their total amount of likes, followers and people they are following. The way it is now, it shows the total amount of likes, followers and following as a whole number and if it's too long it will go over other words on the page.
So how do I use abbreviations like: K(for thousands), m(millions) etc ? This is what I have now.
$stmt = $con->prepare('SELECT name, username, num_likes, profile_pic FROM users WHERE user_closed = "0"
ORDER BY num_likes DESC LIMIT 100');
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($name, $username, $num_likes, $profile_pic);
function convert($num_likes)
{
$num_likes = $number / 1000;
return $num_likes . 'k';
}
This is how I show the result: <p> Total Likes: " . $num_likes ."</p>
I tried the following:
PHP Count round thousand to a K style count like facebook Share . . . Twitter Button ect
Shorten long numbers to K/M/B?
PHP Count round thousand to a K style count Facebook Share
First of all, your function:
function convert($num_likes)
{
$num_likes = $number / 1000;
return $num_likes . 'k';
}
will not work as expected, because it converts to the opposite way :) Here is updated version:
function convert($num_likes)
{
$number = $num_likes / 1000;
return $number . 'k';
}
Second point. You should use the function somewhere... for example your line (actually only a part of it):
<p> Total Likes: " . $num_likes ."</p>
must be:
<p> Total Likes: " . convert($num_likes) ."</p>
And finally, using this answer we can modify convert function to this:
function convert($n) {
if ($n < 1000) {
$n_format = number_format($n);
} else if ($n < 1000000) {
// Anything less than a million
$n_format = number_format($n / 1000, 3) . 'k';
} 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';
}
return $n_format;
}
Now we can convert all numbers up to billions.
Playground: click.
Perhaps like this,
Use round() if you don't want large fractions.
<?php
function convert(int $number)
{
if ($number >= 1E9) {
return round($number / 1E9, 2).'b';
} else if ($number >= 1E6) {
return round($number / 1E6, 2).'m';
} else if ($number >= 1E3) {
return round($number / 1E3, 2).'k';
}
return $number;
}
echo convert(1000000000).PHP_EOL; // 1b
echo convert(1000000).PHP_EOL; // 1m
echo convert(1200).PHP_EOL; // 1.2k
echo convert(1234).PHP_EOL; // 1.23k
echo convert(100).PHP_EOL; // 100
https://3v4l.org/cc54H
I want to convert a number into a string representation with a format similar to Stack Overflow reputation display.
e.g.
999 == '999'
1000 == '1,000'
9999 == '9,999'
10000 == '10k'
10100 == '10.1k'
Another approach that produces exactly the desired output:
function getRepString (rep) {
rep = rep+''; // coerce to string
if (rep < 1000) {
return rep; // return the same number
}
if (rep < 10000) { // place a comma between
return rep.charAt(0) + ',' + rep.substring(1);
}
// divide and format
return (rep/1000).toFixed(rep % 1000 != 0)+'k';
}
Check the output results here.
UPDATE:
CMS got the check and provides a superior answer. Send any more votes his way.
// formats a number similar to the way stack exchange sites
// format reputation. e.g.
// for numbers< 10000 the output is '9,999'
// for numbers > 10000 the output is '10k' with one decimal place when needed
function getRepString(rep)
{
var repString;
if (rep < 1000)
{
repString = rep;
}
else if (rep < 10000)
{
// removed my rube goldberg contraption and lifted
// CMS version of this segment
repString = rep.charAt(0) + ',' + rep.substring(1);
}
else
{
repString = (Math.round((rep / 1000) * 10) / 10) + "k"
}
return repString.toString();
}
Output:
getRepString(999) == '999'
getRepString(1000) == '1,000'
getRepString(9999) == '9,999'
getRepString(10000) == '10k'
getRepString(10100) == '10.1k'
Here is a function in PHP which is part of iZend - http://www.izend.org/en/manual/library/countformat:
function count_format($n, $point='.', $sep=',') {
if ($n < 0) {
return 0;
}
if ($n < 10000) {
return number_format($n, 0, $point, $sep);
}
$d = $n < 1000000 ? 1000 : 1000000;
$f = round($n / $d, 1);
return number_format($f, $f - intval($f) ? 1 : 0, $point, $sep) . ($d == 1000 ? 'k' : 'M');
}
Here is CMS's version in PHP (in case someone needed it, like I did):
function getRepString($rep) {
$rep = intval($rep);
if ($rep < 1000) {
return (string)$rep;
}
if ($rep < 10000) {
return number_format($rep);
}
return number_format(($rep / 1000), ($rep % 1000 != 0)) . 'k';
}
// TEST
var_dump(getRepString(999));
var_dump(getRepString(1000));
var_dump(getRepString(9999));
var_dump(getRepString(10000));
var_dump(getRepString(10100));
Output:
string(3) "999"
string(5) "1,000"
string(5) "9,999"
string(3) "10k"
string(5) "10.1k"
Handlebars.registerHelper("classNameHere",function(rep) {
var repString;
if (rep < 1000)
{
repString = rep;
}
else if (rep < 10000)
{
rep = String(rep);
r = rep.charAt(0);
s = rep.substring(1);
repString = r + ',' + s;
}
else
{
repDecimal = Math.round(rep / 100) / 10;
repString = repDecimal + "k";
}
return repString.toString();
});
divide by 1000 then if result is greater than 1 round the number and concantenate a "k" on the end.
If the result is less than 1 just output the actual result!
// 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;
}
This worked for me. I hope, this will help you. Thanks for asking this question.
I created an npm (and bower) module to do this:
npm install --save approximate-number
Usage:
var approx = require('approximate-number');
approx(123456); // "123k"
I need to generate 16 characters long string (from SHA1 hash), which contains only 0 and 1, with probability 50% (statistically in most cases same amount of 1 in string as amount of 0's).
So i wrote benchmark, and i tried converting each $hash character to binary.
Results are bad, i mean, if im adding leading zeros to binary converted hash, correct probability is far from correct.
When im not adding leading zeros to binary conversion, probability is close to correct:
Percentage all 0 or all 1: 0.0012%
Percentage all 0 or all 1 except 1 character : 0.0146%
Percentage all 0 or all 1 except 2 characters: 0.0812%
But its still far from true correct probability that code below should produce which is:
Percentage all 0 or all 1: 0.003%
Percentage all 0 or all 1 except 1 character : 0.048%
Percentage all 0 or all 1 except 2 characters: 0.376%
How do i know its correct probability? I changed binary conversion to simple mt_rand(0,1) sixteen times (and other confirmation tests).
It must be generated from sha1 hash, to be deterministic by that hash.
Anyone have idea, how to fix my code to produce correct probability results? I tried already for 10 hours straight.
function binary($text){
$list = '';
$temp = '';
$i = 0;
while ($i < 16){
if (is_numeric($text[$i])){
$list .= decbin( $text[$i] );//sprintf( "%08d", decbin( $text[$i] ));
} else {
$temp = ord($text[$i]);
$list .= decbin( $temp );
// $list .= sprintf( "%08d", decbin( $temp ));// substr("00000000",0,8 - strlen($temp)) . $temp;
}
$i++;
}
return $list;
}
$y = 0;
$trafien = 0;
$trafien1= 0;
$trafien2= 0;
$max = 500000;
while ($y < $max){
$time = uniqid() . mt_rand(1,999999999999);
$seed = 'eqm2890rmn9ou8nr9q2';
$hash = sha1($time . $seed);
$last4 = substr($hash, 0, 40);
$binary = binary($last4);
$final = substr($binary, 0,16);
$ile = substr_count($final, '0');
$ile2= substr_count($final, '1');
if ($ile == 16 || $ile2 == 16){
echo "\n".$last4 ." " . 'binary: '. $binary .' final: '. $final;
$trafien += 1;
}
if ($ile == 15 || $ile2 == 15){
$trafien1 += 1;
}
if ($ile == 14 || $ile2 == 14){
$trafien2 += 1;
}
$y++;
}
$procent = ($trafien * 100) / $max;
$procent1= ($trafien1 * 100) / $max;
$procent2= ($trafien2 * 100) / $max;
echo "\nPercentage all 0 or all 1: ". $procent . "%";
echo "\nPercentage all 0 or all 1 except 1 character : ". $procent1 . "%";
echo "\nPercentage all 0 or all 1 except 2 characters: ". $procent2 . "%";
I guess I don't see why you need to reinvent the wheel here or use sha1() when you only use 4 characters and convert to binary. This seems to work fine:
$n = null;
for ($i=1; $i<=16; $i++) {
$n .= mt_rand(0,1);
}
Here is a benchmark script I wrote:
// $app for number of appearances
$app[0] = 0;
$app[1] = 0;
$sample = 10000;
for ($t=1; $t<=$sample; $t++) {
$n = null;
for ($i=1; $i<=16; $i++) {
$n .= mt_rand(0,1);
}
$app[0] += substr_count($n, 0);
$app[1] += substr_count($n, 1);
}
print_r($app);
echo "Probability of 0: ".($app[0] / ($sample * 16))."\n";
echo "Probability of 1: ".($app[1] / ($sample * 16))."\n";
Output with 10000 sample size:
Array
(
[0] => 80079
[1] => 79921
)
Probability of 0: 0.50049375
Probability of 1: 0.49950625
Output with 100000 sample size:
Array
(
[0] => 799390
[1] => 800610
)
Probability of 0: 0.49961875
Probability of 1: 0.50038125
Ok i solved it, i overwork this due to lack of knowledge. You can use direct raw binary output of sha1 function sha1(data, true). Then you have true deterministic 0/1 randomness :)
Here is the problem, when it encounters fractions like: 300/10 instead of giving a result of "30"
the following code gives me: 1/0
$tokens = explode('/', $value);
while ($tokens[0] % 10 == 0) {
$tokens[0] = $tokens[0] / 10;
$tokens[1] = $tokens[1] / 10;
}
if ($tokens[1] == 1) {
return $tokens[0].' s';
} else {
return '1/'.floor(1/($tokens[0]/$tokens[1])).' s';
// return $tokens[0].'/'.$tokens[1].' s';
}
thanks
You should change the line while($tokens[0] % 10 === 0 && $tokens[1] % 10 === 0) { to while($tokens[0] % 10 === 0 && $tokens[1] % 10 === 0) {.
And the line return '1/'.floor(1/($tokens[0]/$tokens[1])).' s'; is not reliable.
If you want to reduce fractions, try this function:
function reduceFraction($fraction) {
sscanf($fraction, '%d/%d %s', $numerator, $denominator, $junk);
// TODO: validation
if( $denominator === null ) {
return (string)$numerator;
}
if( $numerator === $denominator ) {
return 1;
}
$max = max(array($numerator, $denominator));
for($i = 1; $i < $max; ++$i) {
if( $denominator % $i === 0 && $numerator % $i === 0) {
$common = $i;
}
}
if( $denominator === $common ) {
return (string)($numerator / $common);
}
return ($numerator / $common) . '/' . ($denominator / $common);
}
You could use it like this:
reduceFraction('300/10') . ' s';
It's also possible to generalize more the function for chained fractions (eg: '300/100/10'). I can send an implementation of it if you wish.
tell me why the "while ($tokens[0] % 10 == 0 && $tokens[1] % 10 ==0)"
would be better to use than just "while ($tokens[0] % 100 == 0)" since
both methods seem to work ok
If you try to use the string "3000/10" as an argument for each implementation, the one with while ($tokens[0] % 10 == 0 && $tokens[1] % 10 ==0) will return 300 s, and the other with while ($tokens[0] % 100 == 0) will return 1/0 s.
If you use the while ($tokens[0] % 100 == 0) method, the loop iterations are:
$tokens[0] = 3000 / 10 = 300;
$tokens[1] = 10 / 10 = 10;
$tokens[0] = 30 / 10 = 30;
$tokens[1] = 10 / 1 = .1;
Stopped because 30 % 100 != 0.
Since the $token[1] is not 1, it does not return "30 s".
1/30 is less than zero (0.0333...), thus floor(1/30) = 0. That's why it returns "1/0 s".
If you use the while ($tokens[0] % 10 == 0 && $tokens[1] % 10 == 0) method, the loop iterations are:
$tokens[0] = 3000 / 10 = 300;
$tokens[1] = 10 / 10 = 1;
Stopped because 1 % 10 != 0.
Since the $token[1] is not 1, it returns "30 s".
It is better because it will work with more inputs.
But I recommend you to use the "reduceFraction" function that I implemented.
It uses the maximum common denominator technique to reduce functions.
echo reduceFraction('3000/10'); outputs "300".
echo reduceFraction('300/10'); outputs "30".
echo reduceFraction('30/10'); outputs "3".
echo reduceFraction('3/10'); outputs "3/10".
echo reduceFraction('3/3'); outputs "1".
echo reduceFraction('222/444'); outputs "1/2".
echo reduceFraction('444/222'); outputs "2".