Related
This question already has answers here:
PHP Fatal error: Using $this when not in object context
(9 answers)
Closed 7 years ago.
I have the below function, But when I run the code make error like:
Fatal error: Using $this when not in object context in E:....
How to fix it. I replace $this-> with self:: but it failed too.
Please help in this regards,
<?php
function cehck_files()
{
$file1 = 'C:\xampp\htdocs\test\test1.php';
$file2 = 'C:\xampp\htdocs\test\test2.php';
$test = $this->compareFiles($file1,$file2,true);
$test_display = $this->toTable($test);
echo "<pre>";
print_r($test_display);
print_r($test);
echo "</pre>";
}
function compareFiles($file1, $file2, $compareCharacters = false) {
return $this->compare(file_get_contents($file1),file_get_contents($file2),$compareCharacters);
}
function compare($string1, $string2, $compareCharacters = false) {
$start = 0;
if ($compareCharacters){
$sequence1 = $string1;
$sequence2 = $string2;
$end1 = strlen($string1) - 1;
$end2 = strlen($string2) - 1;
} else {
$sequence1 = preg_split('/\R/', $string1);
$sequence2 = preg_split('/\R/', $string2);
$end1 = count($sequence1) - 1;
$end2 = count($sequence2) - 1;
}
// skip any common prefix
while ($start <= $end1 && $start <= $end2 && $sequence1[$start] == $sequence2[$start]) {
$start ++;
}
// skip any common suffix
while ($end1 >= $start && $end2 >= $start && $sequence1[$end1] == $sequence2[$end2]) {
$end1 --;
$end2 --;
}
// compute the table of longest common subsequence lengths
$table = self::computeTable($sequence1, $sequence2, $start, $end1, $end2);
// generate the partial diff
$partialDiff =
self::generatePartialDiff($table, $sequence1, $sequence2, $start);
// generate the full diff
$diff = array();
for ($index = 0; $index < $start; $index ++){
$diff[] = array($sequence1[$index], UNMODIFIED);
}
while (count($partialDiff) > 0) $diff[] = array_pop($partialDiff);
for ($index = $end1 + 1; $index < ($compareCharacters ? strlen($sequence1) : count($sequence1)); $index ++) {
$diff[] = array($sequence1[$index], UNMODIFIED);
}
// return the diff
return $diff;
}
function computeTable($sequence1, $sequence2, $start, $end1, $end2) {
$length1 = $end1 - $start + 1;
$length2 = $end2 - $start + 1;
// initialise the table
$table = array(array_fill(0, $length2 + 1, 0));
// loop over the rows
for ($index1 = 1; $index1 <= $length1; $index1 ++) {
// create the new row
$table[$index1] = array(0);
// loop over the columns
for ($index2 = 1; $index2 <= $length2; $index2 ++){
// store the longest common subsequence length
if ($sequence1[$index1 + $start - 1] == $sequence2[$index2 + $start - 1]) {
$table[$index1][$index2] = $table[$index1 - 1][$index2 - 1] + 1;
} else {
$table[$index1][$index2] =
max($table[$index1 - 1][$index2], $table[$index1][$index2 - 1]);
}
}
}
// return the table
return $table;
}
function generatePartialDiff( $table, $sequence1, $sequence2, $start ) {
$diff = array();
// initialise the indices
$index1 = count($table) - 1;
$index2 = count($table[0]) - 1;
// loop until there are no items remaining in either sequence
while ($index1 > 0 || $index2 > 0){
// check what has happened to the items at these indices
if ($index1 > 0 && $index2 > 0 && $sequence1[$index1 + $start - 1] == $sequence2[$index2 + $start - 1]) {
// update the diff and the indices
$diff[] = array($sequence1[$index1 + $start - 1], UNMODIFIED);
$index1 --;
$index2 --;
} elseif ($index2 > 0 && $table[$index1][$index2] == $table[$index1][$index2 - 1]) {
// update the diff and the indices
$diff[] = array($sequence2[$index2 + $start - 1], INSERTED);
$index2 --;
}else{
// update the diff and the indices
$diff[] = array($sequence1[$index1 + $start - 1], DELETED);
$index1 --;
}
}
// return the diff
return $diff;
}
function toTable($diff, $indentation = '', $separator = '<br>') {
$html = $indentation . "<table class=\"diff\">\n";
// loop over the lines in the diff
$index = 0;
while ($index < count($diff)){
// determine the line type
switch ($diff[$index][1]){
// display the content on the left and right
case UNMODIFIED:
$leftCell =
self::getCellContent(
$diff, $indentation, $separator, $index, UNMODIFIED);
$rightCell = $leftCell;
break;
// display the deleted on the left and inserted content on the right
case DELETED:
$leftCell =
self::getCellContent(
$diff, $indentation, $separator, $index, DELETED);
$rightCell =
self::getCellContent(
$diff, $indentation, $separator, $index, INSERTED);
break;
// display the inserted content on the right
case INSERTED:
$leftCell = '';
$rightCell =
self::getCellContent(
$diff, $indentation, $separator, $index, INSERTED);
break;
}
// extend the HTML with the new row
$html .=
$indentation
. " <tr>\n"
. $indentation
. ' <td class="diff'
. ($leftCell == $rightCell
? 'Unmodified'
: ($leftCell == '' ? 'Blank' : 'Deleted'))
. '">'
. $leftCell
. "</td>\n"
. $indentation
. ' <td class="diff'
. ($leftCell == $rightCell
? 'Unmodified'
: ($rightCell == '' ? 'Blank' : 'Inserted'))
. '">'
. $rightCell
. "</td>\n"
. $indentation
. " </tr>\n";
}
// return the HTML
return $html . $indentation . "</table>\n";
}
?>
You are using $this for a function which is not a method of any class.
Instead of
$test = $this->compareFiles($file1,$file2,true);
Use:
$test = compareFiles($file1,$file2,true);
Also, change
return $this->compare(file_get_contents($file1),file_get_contents($file2),$compareCharacters);
To
return compare(file_get_contents($file1),file_get_contents($file2),$compareCharacters);
And to the remaining changes in this way.
I am trying to convert calculations keyed in by users with decimal results into fractions. For e.g.; 66.6666666667 into 66 2/3. Any pointers?
Thanx in advance
Continued fractions can be used to find rational approximations to real numbers that are "best" in a strict sense. Here's a PHP function that finds a rational approximation to a given (positive) floating point number with a relative error less than $tolerance:
<?php
function float2rat($n, $tolerance = 1.e-6) {
$h1=1; $h2=0;
$k1=0; $k2=1;
$b = 1/$n;
do {
$b = 1/$b;
$a = floor($b);
$aux = $h1; $h1 = $a*$h1+$h2; $h2 = $aux;
$aux = $k1; $k1 = $a*$k1+$k2; $k2 = $aux;
$b = $b-$a;
} while (abs($n-$h1/$k1) > $n*$tolerance);
return "$h1/$k1";
}
printf("%s\n", float2rat(66.66667)); # 200/3
printf("%s\n", float2rat(sqrt(2))); # 1393/985
printf("%s\n", float2rat(0.43212)); # 748/1731
I have written more about this algorithm and why it works, and even a JavaScript demo here: https://web.archive.org/web/20180731235708/http://jonisalonen.com/2012/converting-decimal-numbers-to-ratios/
Farey fractions can be quite useful in this case.
They can be used to convert any decimal into a fraction with the lowest possible denominator.
Sorry - I don't have a prototype in PHP, so here's one in Python:
def farey(v, lim):
"""No error checking on args. lim = maximum denominator.
Results are (numerator, denominator); (1, 0) is 'infinity'."""
if v < 0:
n, d = farey(-v, lim)
return (-n, d)
z = lim - lim # Get a "zero of the right type" for the denominator
lower, upper = (z, z+1), (z+1, z)
while True:
mediant = (lower[0] + upper[0]), (lower[1] + upper[1])
if v * mediant[1] > mediant[0]:
if lim < mediant[1]:
return upper
lower = mediant
elif v * mediant[1] == mediant[0]:
if lim >= mediant[1]:
return mediant
if lower[1] < upper[1]:
return lower
return upper
else:
if lim < mediant[1]:
return lower
upper = mediant
Converted Python code in answer from #APerson241 to PHP
<?php
function farey($v, $lim) {
// No error checking on args. lim = maximum denominator.
// Results are array(numerator, denominator); array(1, 0) is 'infinity'.
if($v < 0) {
list($n, $d) = farey(-$v, $lim);
return array(-$n, $d);
}
$z = $lim - $lim; // Get a "zero of the right type" for the denominator
list($lower, $upper) = array(array($z, $z+1), array($z+1, $z));
while(true) {
$mediant = array(($lower[0] + $upper[0]), ($lower[1] + $upper[1]));
if($v * $mediant[1] > $mediant[0]) {
if($lim < $mediant[1])
return $upper;
$lower = $mediant;
}
else if($v * $mediant[1] == $mediant[0]) {
if($lim >= $mediant[1])
return $mediant;
if($lower[1] < $upper[1])
return $lower;
return $upper;
}
else {
if($lim < $mediant[1])
return $lower;
$upper = $mediant;
}
}
}
// Example use:
$f = farey(66.66667, 10);
echo $f[0], '/', $f[1], "\n"; # 200/3
$f = farey(sqrt(2), 1000);
echo $f[0], '/', $f[1], "\n"; # 1393/985
$f = farey(0.43212, 2000);
echo $f[0], '/', $f[1], "\n"; # 748/1731
Based upon #Joni's answer, here is what I used to pull out the whole number.
function convert_decimal_to_fraction($decimal){
$big_fraction = float2rat($decimal);
$num_array = explode('/', $big_fraction);
$numerator = $num_array[0];
$denominator = $num_array[1];
$whole_number = floor( $numerator / $denominator );
$numerator = $numerator % $denominator;
if($numerator == 0){
return $whole_number;
}else if ($whole_number == 0){
return $numerator . '/' . $denominator;
}else{
return $whole_number . ' ' . $numerator . '/' . $denominator;
}
}
function float2rat($n, $tolerance = 1.e-6) {
$h1=1; $h2=0;
$k1=0; $k2=1;
$b = 1/$n;
do {
$b = 1/$b;
$a = floor($b);
$aux = $h1; $h1 = $a*$h1+$h2; $h2 = $aux;
$aux = $k1; $k1 = $a*$k1+$k2; $k2 = $aux;
$b = $b-$a;
} while (abs($n-$h1/$k1) > $n*$tolerance);
return "$h1/$k1";
}
Based on #APerson's and #Jeff Monteiro's answers I've created PHP version of Farey fractions that will be simplified to whole values with fractions with lowest possible denominator:
<?php
class QuantityTransform
{
/**
* #see https://stackoverflow.com/questions/14330713/converting-float-decimal-to-fraction
*/
public static function decimalToFraction(float $decimal, $glue = ' ', int $limes = 10): string
{
if (null === $decimal || $decimal < 0.001) {
return '';
}
$wholeNumber = (int) floor($decimal);
$remainingDecimal = $decimal - $wholeNumber;
[$numerator, $denominator] = self::fareyFraction($remainingDecimal, $limes);
// Values rounded to 1 should be added to base value and returned without fraction part
if (is_int($simplifiedFraction = $numerator / $denominator)) {
$wholeNumber += $simplifiedFraction;
$numerator = 0;
}
return (0 === $wholeNumber && 0 === $numerator)
// Too small values will be returned in original format
? (string) $decimal
// Otherwise let's format value - only non-0 whole value / fractions will be returned
: trim(sprintf(
'%s%s%s',
(string) $wholeNumber ?: '',
$wholeNumber > 0 ? $glue : '',
0 === $numerator ? '' : ($numerator . '/' . $denominator)
));
}
/**
* #see https://stackoverflow.com/a/14330799/842480
*
* #return int[] Numerator and Denominator values
*/
private static function fareyFraction(float $value, int $limes): array
{
if ($value < 0) {
[$numerator, $denominator] = self::fareyFraction(-$value, $limes);
return [-$numerator, $denominator];
}
$zero = $limes - $limes;
$lower = [$zero, $zero + 1];
$upper = [$zero + 1, $zero];
while (true) {
$mediant = [$lower[0] + $upper[0], $lower[1] + $upper[1]];
if ($value * $mediant[1] > $mediant[0]) {
if ($limes < $mediant[1]) {
return $upper;
}
$lower = $mediant;
} elseif ($value * $mediant[1] === $mediant[0]) {
if ($limes >= $mediant[1]) {
return $mediant;
}
if ($lower[1] < $upper[1]) {
return $lower;
}
return $upper;
} else {
if ($limes < $mediant[1]) {
return $lower;
}
$upper = $mediant;
}
}
}
}
Then you san use it like:
QuantityTransform::decimalToFraction(0.06); // 0.06
QuantityTransform::decimalToFraction(0.75); // 3/4
QuantityTransform::decimalToFraction(1.75, ' and '); // 1 and 3/4
QuantityTransform::decimalToFraction(2.33, ' and '); // 2 and 1/3
QuantityTransform::decimalToFraction(2.58, ' ', 5); // 2 3/5
QuantityTransform::decimalToFraction(2.58, ' & ', 10); // 2 & 4/7
QuantityTransform::decimalToFraction(1.97); // 2
Here is my approach to this problem. Works fine with rational numbers.
function dec2fracso($dec){
//Negative number flag.
$num=$dec;
if($num<0){
$neg=true;
}else{
$neg=false;
}
//Extracts 2 strings from input number
$decarr=explode('.',(string)$dec);
//Checks for divided by zero input.
if($decarr[1]==0){
$decarr[1]=1;
$fraccion[0]=$decarr[0];
$fraccion[1]=$decarr[1];
return $fraccion;
}
//Calculates the divisor before simplification.
$long=strlen($decarr[1]);
$div="1";
for($x=0;$x<$long;$x++){
$div.="0";
}
//Gets the greatest common divisor.
$x=(int)$decarr[1];
$y=(int)$div;
$gcd=gmp_strval(gmp_gcd($x,$y));
//Calculates the result and fills the array with the correct sign.
if($neg){
$fraccion[0]=((abs($decarr[0])*($y/$gcd))+($x/$gcd))*(-1);
}else{
$fraccion[0]=(abs($decarr[0])*($y/$gcd))+($x/$gcd);
}
$fraccion[1]=($y/$gcd);
return $fraccion;
}
Sometimes it is necessary to treat only the decimals of a float. So I created a code that uses the function created by #Joni to present a format that is quite common in culinary recipes, at least in Brazil.
So instead of using 3/2 which is the result for 1.5, using the function I created it is possible to present the value 1 1/2, and if you want, you can also add a string to concatenate the values, creating something like "1 and 1/2 ".
function float2rat($n, $tolerance = 1.e-6) {
$h1=1; $h2=0;
$k1=0; $k2=1;
$b = 1/$n;
do {
$b = 1/$b;
$a = floor($b);
$aux = $h1; $h1 = $a*$h1+$h2; $h2 = $aux;
$aux = $k1; $k1 = $a*$k1+$k2; $k2 = $aux;
$b = $b-$a;
} while (abs($n-$h1/$k1) > $n*$tolerance);
return "$h1/$k1";
}
function float2fraction($float, $concat = ' '){
// ensures that the number is float,
// even when the parameter is a string
$float = (float)$float;
if($float == 0 ){
return $float;
}
// when float between -1 and 1
if( $float > -1 && $float < 0 || $float < 1 && $float > 0 ){
$fraction = float2rat($float);
return $fraction;
}
else{
// get the minor integer
if( $float < 0 ){
$integer = ceil($float);
}
else{
$integer = floor($float);
}
// get the decimal
$decimal = $float - $integer;
if( $decimal != 0 ){
$fraction = float2rat(abs($decimal));
$fraction = $integer . $concat . $fraction;
return $fraction;
}
else{
return $float;
}
}
}
Usage e.g:
echo float2fraction(1.5);
will return "1 1/2"
I have a question about formatting the Rupee currency (Indian Rupee - INR).
For example, numbers here are represented as:
1
10
100
1,000
10,000
1,00,000
10,00,000
1,00,00,000
10,00,00,000
Refer Indian Numbering System
I have to do with it PHP.
I have saw this question Displaying Currency in Indian Numbering Format. But couldn't able to get it for PHP my problem.
Update:
How to use money_format() in indian currency format?
You have so many options but money_format can do the trick for you.
Example:
$amount = '100000';
setlocale(LC_MONETARY, 'en_IN');
$amount = money_format('%!i', $amount);
echo $amount;
Output:
1,00,000.00
Note:
The function money_format() is only defined if the system has strfmon capabilities. For example, Windows does not, so money_format() is undefined in Windows.
Pure PHP Implementation - Works on any system:
$amount = '10000034000';
$amount = moneyFormatIndia( $amount );
echo $amount;
function moneyFormatIndia($num) {
$explrestunits = "" ;
if(strlen($num)>3) {
$lastthree = substr($num, strlen($num)-3, strlen($num));
$restunits = substr($num, 0, strlen($num)-3); // extracts the last three digits
$restunits = (strlen($restunits)%2 == 1)?"0".$restunits:$restunits; // explodes the remaining digits in 2's formats, adds a zero in the beginning to maintain the 2's grouping.
$expunit = str_split($restunits, 2);
for($i=0; $i<sizeof($expunit); $i++) {
// creates each of the 2's group and adds a comma to the end
if($i==0) {
$explrestunits .= (int)$expunit[$i].","; // if is first value , convert into integer
} else {
$explrestunits .= $expunit[$i].",";
}
}
$thecash = $explrestunits.$lastthree;
} else {
$thecash = $num;
}
return $thecash; // writes the final format where $currency is the currency symbol.
}
$num = 1234567890.123;
$num = preg_replace("/(\d+?)(?=(\d\d)+(\d)(?!\d))(\.\d+)?/i", "$1,", $num);
echo $num;
// Input : 1234567890.123
// Output : 1,23,45,67,890.123
// Input : -1234567890.123
// Output : -1,23,45,67,890.123
echo 'Rs. '.IND_money_format(1234567890);
function IND_money_format($money){
$len = strlen($money);
$m = '';
$money = strrev($money);
for($i=0;$i<$len;$i++){
if(( $i==3 || ($i>3 && ($i-1)%2==0) )&& $i!=$len){
$m .=',';
}
$m .=$money[$i];
}
return strrev($m);
}
NOTE:: it is not tested on float values and it suitable for only Integer
The example you've linked is making use of the ICU libraries which are available with PHP in the intl ExtensionDocs:
$fmt = new NumberFormatter($locale = 'en_IN', NumberFormatter::CURRENCY);
echo $fmt->format(10000000000.1234)."\n"; # Rs 10,00,00,00,000.12
Or maybe better fitting in your case:
$fmt = new NumberFormatter($locale = 'en_IN', NumberFormatter::DECIMAL);
echo $fmt->format(10000000000)."\n"; # 10,00,00,00,000
Simply use below function to format in INR.
function amount_inr_format($amount) {
$fmt = new \NumberFormatter($locale = 'en_IN', NumberFormatter::DECIMAL);
return $fmt->format($amount);
}
Check this code, it works 100% for Indian Rupees format with decimal format.
You can use numbers like :
123456.789
123.456
123.4
123
and 1,2,3,4,5,6,7,8,9,.222
function moneyFormatIndia($num){
$explrestunits = "" ;
$num = preg_replace('/,+/', '', $num);
$words = explode(".", $num);
$des = "00";
if(count($words)<=2){
$num=$words[0];
if(count($words)>=2){$des=$words[1];}
if(strlen($des)<2){$des="$des";}else{$des=substr($des,0,2);}
}
if(strlen($num)>3){
$lastthree = substr($num, strlen($num)-3, strlen($num));
$restunits = substr($num, 0, strlen($num)-3); // extracts the last three digits
$restunits = (strlen($restunits)%2 == 1)?"0".$restunits:$restunits; // explodes the remaining digits in 2's formats, adds a zero in the beginning to maintain the 2's grouping.
$expunit = str_split($restunits, 2);
for($i=0; $i<sizeof($expunit); $i++){
// creates each of the 2's group and adds a comma to the end
if($i==0)
{
$explrestunits .= (int)$expunit[$i].","; // if is first value , convert into integer
}else{
$explrestunits .= $expunit[$i].",";
}
}
$thecash = $explrestunits.$lastthree;
} else {
$thecash = $num;
}
return "$thecash.$des"; // writes the final format where $currency is the currency symbol.
}
When money_format is not available :
function format($amount): string
{
list ($number, $decimal) = explode('.', sprintf('%.2f', floatval($amount)));
$sign = $number < 0 ? '-' : '';
$number = abs($number);
for ($i = 3; $i < strlen($number); $i += 3)
{
$number = substr_replace($number, ',', -$i, 0);
}
return $sign . $number . '.' . $decimal;
}
<?php
$amount = '-100000.22222'; // output -1,00,000.22
//$amount = '0100000.22222'; // output 1,00,000.22
//$amount = '100000.22222'; // output 1,00,000.22
//$amount = '100000.'; // output 1,00,000.00
//$amount = '100000.2'; // output 1,00,000.20
//$amount = '100000.0'; // output 1,00,000.00
//$amount = '100000'; // output 1,00,000.00
echo $aaa = moneyFormatIndia($amount);
function moneyFormatIndia($amount)
{
$amount = round($amount,2);
$amountArray = explode('.', $amount);
if(count($amountArray)==1)
{
$int = $amountArray[0];
$des=00;
}
else {
$int = $amountArray[0];
$des=$amountArray[1];
}
if(strlen($des)==1)
{
$des=$des."0";
}
if($int>=0)
{
$int = numFormatIndia( $int );
$themoney = $int.".".$des;
}
else
{
$int=abs($int);
$int = numFormatIndia( $int );
$themoney= "-".$int.".".$des;
}
return $themoney;
}
function numFormatIndia($num)
{
$explrestunits = "";
if(strlen($num)>3)
{
$lastthree = substr($num, strlen($num)-3, strlen($num));
$restunits = substr($num, 0, strlen($num)-3); // extracts the last three digits
$restunits = (strlen($restunits)%2 == 1)?"0".$restunits:$restunits; // explodes the remaining digits in 2's formats, adds a zero in the beginning to maintain the 2's grouping.
$expunit = str_split($restunits, 2);
for($i=0; $i<sizeof($expunit); $i++) {
// creates each of the 2's group and adds a comma to the end
if($i==0) {
$explrestunits .= (int)$expunit[$i].","; // if is first value , convert into integer
} else {
$explrestunits .= $expunit[$i].",";
}
}
$thecash = $explrestunits.$lastthree;
} else {
$thecash = $num;
}
return $thecash; // writes the final format where $currency is the currency symbol.
}
?>
So if I'm reading that right, the Indian Numbering System separates the thousands, then every power of a hundred past that? Hmm...
Perhaps something like this?
function indian_number_format($num) {
$num = "".$num;
if( strlen($num) < 4) return $num;
$tail = substr($num,-3);
$head = substr($num,0,-3);
$head = preg_replace("/\B(?=(?:\d{2})+(?!\d))/",",",$head);
return $head.",".$tail;
}
$amount=-3000000000111.11;
$amount<0?(($sign='-').($amount*=-1)):$sign=''; //Extracting sign from given amount
$pos=strpos($amount, '.'); //Identifying the decimal point position
$amt= substr($amount, $pos-3); // Extracting last 3 digits of integer part along with fractional part
$amount= substr($amount,0, $pos-3); //removing the extracted part from amount
for(;strlen($amount);$amount=substr($amount,0,-2)) // Now loop through each 2 digits of remaining integer part
$amt=substr ($amount,-2).','.$amt; //forming Indian Currency format by appending (,) for each 2 digits
echo $sign.$amt; //Appending sign
I think this a quick and simplest solution:-
function formatToInr($number){
$number=round($number,2);
// windows is not supported money_format
if(setlocale(LC_MONETARY, 'en_IN')){
return money_format('%!'.$decimal.'n', $number);
}
else {
if(floor($number) == $number) {
$append='.00';
}else{
$append='';
}
$number = preg_replace("/(\d+?)(?=(\d\d)+(\d)(?!\d))(\.\d+)?/i", "$1,", $number);
return $number.$append;
}
}
You should check the number_format function.Here is the link
Separating thousands with commas will look like
$rupias = number_format($number, 2, ',', ',');
I have used different format parameters to money_format() for my output.
setlocale(LC_MONETARY, 'en_IN');
if (ctype_digit($amount) ) {
// is whole number
// if not required any numbers after decimal use this format
$amount = money_format('%!.0n', $amount);
}
else {
// is not whole number
$amount = money_format('%!i', $amount);
}
//$amount=10043445.7887 outputs 1,00,43,445.79
//$amount=10043445 outputs 1,00,43,445
Above Function Not working with Decimal
$amount = 10000034000.001;
$amount = moneyFormatIndia( $amount );
echo $amount;
function moneyFormatIndia($num){
$nums = explode(".",$num);
if(count($nums)>2){
return "0";
}else{
if(count($nums)==1){
$nums[1]="00";
}
$num = $nums[0];
$explrestunits = "" ;
if(strlen($num)>3){
$lastthree = substr($num, strlen($num)-3, strlen($num));
$restunits = substr($num, 0, strlen($num)-3);
$restunits = (strlen($restunits)%2 == 1)?"0".$restunits:$restunits;
$expunit = str_split($restunits, 2);
for($i=0; $i<sizeof($expunit); $i++){
if($i==0)
{
$explrestunits .= (int)$expunit[$i].",";
}else{
$explrestunits .= $expunit[$i].",";
}
}
$thecash = $explrestunits.$lastthree;
} else {
$thecash = $num;
}
return $thecash.".".$nums[1];
}
}
Answer : 10,00,00,34,000.001
It's my very own function to do the task
function bd_money($num) {
$pre = NULL; $sep = array(); $app = '00';
$s=substr($num,0,1);
if ($s=='-') {$pre= '-';$num = substr($num,1);}
$num=explode('.',$num);
if (count($num)>1) $app=$num[1];
if (strlen($num[0])<4) return $pre . $num[0] . '.' . $app;
$th=substr($num[0],-3);
$hu=substr($num[0],0,-3);
while(strlen($hu)>0){$sep[]=substr($hu,-2); $hu=substr($hu,0,-2);}
return $pre.implode(',',array_reverse($sep)).','.$th.'.'.$app;
}
It took 0.0110 Seconds per THOUSAND query while number_format took 0.001 only.
Always try to use PHP native functions only when performance is target issue.
$r=explode('.',12345601.20);
$n = $r[0];
$len = strlen($n); //lenght of the no
$num = substr($n,$len-3,3); //get the last 3 digits
$n = $n/1000; //omit the last 3 digits already stored in $num
while($n > 0) //loop the process - further get digits 2 by 2
{
$len = strlen($n);
$num = substr($n,$len-2,2).",".$num;
$n = round($n/100);
}
echo "Rs.".$num.'.'.$r[1];
If you dont want to use any inbuilt function in my case i was doing on iis server so was unable to use one the function in php so did this
$num = -21324322.23;
moneyFormatIndiaPHP($num);
function moneyFormatIndiaPHP($num){
//converting it to string
$numToString = (string)$num;
//take care of decimal values
$change = explode('.', $numToString);
//taking care of minus sign
$checkifminus = explode('-', $change[0]);
//if minus then change the value as per
$change[0] = (count($checkifminus) > 1)? $checkifminus[1] : $checkifminus[0];
//store the minus sign for further
$min_sgn = '';
$min_sgn = (count($checkifminus) > 1)?'-':'';
//catch the last three
$lastThree = substr($change[0], strlen($change[0])-3);
//catch the other three
$ExlastThree = substr($change[0], 0 ,strlen($change[0])-3);
//check whethr empty
if($ExlastThree != '')
$lastThree = ',' . $lastThree;
//replace through regex
$res = preg_replace("/\B(?=(\d{2})+(?!\d))/",",",$ExlastThree);
//main container num
$lst = '';
if(isset($change[1]) == ''){
$lst = $min_sgn.$res.$lastThree;
}else{
$lst = $min_sgn.$res.$lastThree.".".$change[1];
}
//special case if equals to 2 then
if(strlen($change[0]) === 2){
$lst = str_replace(",","",$lst);
}
return $lst;
}
This for both integer and float values
function indian_money_format($number)
{
if(strstr($number,"-"))
{
$number = str_replace("-","",$number);
$negative = "-";
}
$split_number = #explode(".",$number);
$rupee = $split_number[0];
$paise = #$split_number[1];
if(#strlen($rupee)>3)
{
$hundreds = substr($rupee,strlen($rupee)-3);
$thousands_in_reverse = strrev(substr($rupee,0,strlen($rupee)-3));
$thousands = '';
for($i=0; $i<(strlen($thousands_in_reverse)); $i=$i+2)
{
$thousands .= $thousands_in_reverse[$i].$thousands_in_reverse[$i+1].",";
}
$thousands = strrev(trim($thousands,","));
$formatted_rupee = $thousands.",".$hundreds;
}
else
{
$formatted_rupee = $rupee;
}
if((int)$paise>0)
{
$formatted_paise = ".".substr($paise,0,2);
}else{
$formatted_paise = '.00';
}
return $negative.$formatted_rupee.$formatted_paise;
}
Use this function:
function addCommaToRs($amt, &$ret, $dec='', $sign=''){
if(preg_match("/-/",$amt)){
$amts=explode('-',$amt);
$amt=$amts['1'];
static $sign='-';
}
if(preg_match("/\./",$amt)){
$amts=explode('.',$amt);
$amt=$amts['0'];
$l=strlen($amt);
static $dec;
$dec=$amts['1'];
} else {
$l=strlen($amt);
}
if($l>3){
if($l%2==0){
$ret.= substr($amt,0,1);
$ret.= ",";
addCommaToRs(substr($amt,1,$l),$ret,$dec);
} else{
$ret.=substr($amt,0,2);
$ret.= ",";
addCommaToRs(substr($amt,2,$l),$ret,$dec);
}
} else {
$ret.= $amt;
if($dec) $ret.=".".$dec;
}
return $sign.$ret;
}
Call it like this:
$amt = '';
echo addCommaToRs(123456789.123,&$amt,0);
This will return 12,34,567.123.
<?php
function moneyFormatIndia($num)
{
//$num=123456789.00;
$result='';
$sum=explode('.',$num);
$after_dec=$sum[1];
$before_dec=$sum[0];
$result='.'.$after_dec;
$num=$before_dec;
$len=strlen($num);
if($len<=3)
{
$result=$num.$result;
}
else
{
if($len<=5)
{
$result='Rs '.substr($num, 0,$len-3).','.substr($num,$len-3).$result;
return $result;
}
else
{
$ls=strlen($num);
$result=substr($num, $ls-5,2).','.substr($num, $ls-3).$result;
$num=substr($num, 0,$ls-5);
while(strlen($num)!=0)
{
$result=','.$result;
$ls=strlen($num);
if($ls<=2)
{
$result='Rs. '.$num.$result;
return $result;
}
else
{
$result=substr($num, $ls-2).$result;
$num=substr($num, 0,$ls-2);
}
}
}
}
}
?>
heres is simple thing u can do ,
float amount = 100000;
NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("en", "IN"));
String moneyString = formatter.format(amount);
System.out.println(moneyString);
The output will be , Rs.100,000.00 .
declare #Price decimal(26,7)
Set #Price=1234456677
select FORMAT(#Price, 'c', 'en-In')
Result:
1,23,44,56,677.00
How can I convert this:
26.72773551940918
Into something like this:
22°12'42"N
The trick here is that the coordinates are, actually Latitude and Longitude, I just need to format them correctly.
You can find functions to do that here
<?php
function DMStoDEC($deg,$min,$sec)
{
// Converts DMS ( Degrees / minutes / seconds )
// to decimal format longitude / latitude
return $deg+((($min*60)+($sec))/3600);
}
function DECtoDMS($dec)
{
// Converts decimal longitude / latitude to DMS
// ( Degrees / minutes / seconds )
// This is the piece of code which may appear to
// be inefficient, but to avoid issues with floating
// point math we extract the integer part and the float
// part by using a string function.
$vars = explode(".",$dec);
$deg = $vars[0];
$tempma = "0.".$vars[1];
$tempma = $tempma * 3600;
$min = floor($tempma / 60);
$sec = $tempma - ($min*60);
return array("deg"=>$deg,"min"=>$min,"sec"=>$sec);
}
?>
The lat/lon coords are written in (roughly speaking) a base-60 numeral system. Here's how you convert them:
function fraction_to_min_sec($coord)
{
$isnorth = $coord>=0;
$coord = abs($coord);
$deg = floor($coord);
$coord = ($coord-$deg)*60;
$min = floor($coord);
$sec = floor(($coord-$min)*60);
return array($deg, $min, $sec, $isnorth ? 'N' : 'S');
// or if you want the string representation
return sprintf("%d°%d'%d\"%s", $deg, $min, $sec, $isnorth ? 'N' : 'S');
}
I say my function has better numerical stability than #SeRPRo's one.
Here's one where you pass in the latitude,longitude in DMS values and returns the converted DMS string. Easy and simple
function DECtoDMS($latitude, $longitude)
{
$latitudeDirection = $latitude < 0 ? 'S': 'N';
$longitudeDirection = $longitude < 0 ? 'W': 'E';
$latitudeNotation = $latitude < 0 ? '-': '';
$longitudeNotation = $longitude < 0 ? '-': '';
$latitudeInDegrees = floor(abs($latitude));
$longitudeInDegrees = floor(abs($longitude));
$latitudeDecimal = abs($latitude)-$latitudeInDegrees;
$longitudeDecimal = abs($longitude)-$longitudeInDegrees;
$_precision = 3;
$latitudeMinutes = round($latitudeDecimal*60,$_precision);
$longitudeMinutes = round($longitudeDecimal*60,$_precision);
return sprintf('%s%s° %s %s %s%s° %s %s',
$latitudeNotation,
$latitudeInDegrees,
$latitudeMinutes,
$latitudeDirection,
$longitudeNotation,
$longitudeInDegrees,
$longitudeMinutes,
$longitudeDirection
);
}
Here is the opposite when you have DMS string and need it as float number (contains unicode characters):
//e.g.
$dec = dms_to_dec("-18° 51' 30.5697\"");
/**
* Convert a coordinate in dms to dec
*
* #param string $dms coordinate
* #return float
*/
function dms_to_dec($dms)
{
$dms = stripslashes($dms);
$neg = (preg_match('/[SWO]/i', $dms) == 0) ? 1 : -1;
$dms = preg_replace('/(^\s?-)|(\s?[NSEWO]\s?)/i', '', $dms);
$pattern = "/(\\d*\\.?\\d+)(?:[°ºd: ]+)(\\d*\\.?\\d+)*(?:['m′: ])*(\\d*\\.?\\d+)*[\"s″ ]?/i";
$parts = preg_split($pattern, $dms, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
if (!$parts) {
return;
}
// parts: 0 = degree, 1 = minutes, 2 = seconds
$d = isset($parts[0]) ? (float)$parts[0] : 0;
$m = isset($parts[1]) ? (float)$parts[1] : 0;
if (strpos($dms, ".") > 1 && isset($parts[2])) {
$m = (float)($parts[1] . '.' . $parts[2]);
unset($parts[2]);
}
$s = isset($parts[2]) ? (float)$parts[2] : 0;
$dec = ($d + ($m/60) + ($s/3600))*$neg;
return $dec;
}
Ok so I am trying to turn my hit counter to round thousands to a single digit too display 3 thousand hits as 3K for example, like the Facebook Share and Twitter Tweet Buttons do. Here is my code. Any idea what I am doing wrong?
$postresultscount = (($resultscount) ? $resultscount->sumCount : 1);
$k = 1000;
$L = '';
if ($postresultscount > $k) {
$echoxcount = round($postresultscount/$k);
$L = 'K';
} else if ($postresultscount == $k) {
$echoxcount = 1;
$L = 'K';
} else {
$echoxcount = $postresultscount;
}
echo 'document.write("'.$echoxcount.' '.$L.'")';
Here comes a PHP function to format numbers to nearest thousands such as Kilos, Millions, Billions, and Trillions with comma
Function
function thousandsCurrencyFormat($num) {
if($num>1000) {
$x = round($num);
$x_number_format = number_format($x);
$x_array = explode(',', $x_number_format);
$x_parts = array('k', 'm', 'b', 't');
$x_count_parts = count($x_array) - 1;
$x_display = $x;
$x_display = $x_array[0] . ((int) $x_array[1][0] !== 0 ? '.' . $x_array[1][0] : '');
$x_display .= $x_parts[$x_count_parts - 1];
return $x_display;
}
return $num;
}
Output
thousandsCurrencyFormat(3000) - 3k
thousandsCurrencyFormat(35500) - 35.5k
thousandsCurrencyFormat(905000) - 905k
thousandsCurrencyFormat(5500000) - 5.5m
thousandsCurrencyFormat(88800000) - 88.8m
thousandsCurrencyFormat(745000000) - 745m
thousandsCurrencyFormat(2000000000) - 2b
thousandsCurrencyFormat(22200000000) - 22.2b
thousandsCurrencyFormat(1000000000000) - 1t (1 trillion)
Resources
https://code.recuweb.com/2018/php-format-numbers-to-nearest-thousands/
function shortNumber($num)
{
$units = ['', 'K', 'M', 'B', 'T'];
for ($i = 0; $num >= 1000; $i++) {
$num /= 1000;
}
return round($num, 1) . $units[$i];
}
I adapted this one from a function created to display bytes in human readable form by bashy here:
https://laracasts.com/discuss/channels/laravel/human-readable-file-size-and-time
a bit better than the post of Yuki
if ($value > 999 && $value <= 999999) {
$result = floor($value / 1000) . ' K';
} elseif ($value > 999999) {
$result = floor($value / 1000000) . ' M';
} else {
$result = $value;
}
Question is 8 years old but each time I see an answer that contains an else statement, I think it can be done in a better (cleaner) way.
<?php
if (!function_exists('format_number_in_k_notation')) {
function format_number_in_k_notation(int $number): string
{
$suffixByNumber = function () use ($number) {
if ($number < 1000) {
return sprintf('%d', $number);
}
if ($number < 1000000) {
return sprintf('%d%s', floor($number / 1000), 'K+');
}
if ($number >= 1000000 && $number < 1000000000) {
return sprintf('%d%s', floor($number / 1000000), 'M+');
}
if ($number >= 1000000000 && $number < 1000000000000) {
return sprintf('%d%s', floor($number / 1000000000), 'B+');
}
return sprintf('%d%s', floor($number / 1000000000000), 'T+');
};
return $suffixByNumber();
}
}
dump(format_number_in_k_notation(123)); // "123"
dump(format_number_in_k_notation(73000)); // "73K+"
dump(format_number_in_k_notation(216000)); // "216K+"
dump(format_number_in_k_notation(50400123)); // "50M+"
dump(format_number_in_k_notation(12213500100600)); // "12T+"
die;
function print_number_count($number) {
$units = array( '', 'K', 'M', 'B');
$power = $number > 0 ? floor(log($number, 1000)) : 0;
if($power > 0)
return #number_format($number / pow(1000, $power), 2, ',', ' ').' '.$units[$power];
else
return #number_format($number / pow(1000, $power), 0, '', '');
}
My func
function numsize($size,$round=2){
$unit=['', 'K', 'M', 'G', 'T'];
return round($size/pow(1000,($i=floor(log($size,1000)))),$round).$unit[$i];
}
Use floor instead of round if you want 3500 to round down to 3 K.
Otherwise, your code works, albeit problematically. Try this:
if ($postresultscount > 1000) {
$result = floor($postresultscount / 1000) . 'K';
} else {
$result = $postresultscount;
}
echo 'document.write("' . $result . '")";
It also appears you're writing JavaScript using PHP—take care.
This is a modified version with k and m lowercase and show one decimal place for milllions.
<?php
if ($value > 999 && $value <= 999999) {
$result = floor($value / 1000) . 'k';
} elseif ($value > 999999) {
$result = number_format((float)$value , 1, '.', '')/1000000 . 'm';
} else {
$result = $value;
}
?>
Several good answers have already been given to this particularly old question, however, most are too simple for my taste or not easy to extend for more units, so here's what I use:
# The function that returns a number formatted as a string in thousands, millions etc.
public static function getNumberAbbreviation (Int $number, Int $decimals = 1) : String {
# Define the unit size and supported units.
$unitSize = 1000;
$units = ["", "K", "M", "B", "T"];
# Calculate the number of units as the logarithm of the absolute value with the
# unit size as base.
$unitsCount = ($number === 0) ? 0 : floor(log(abs($number), $unitSize));
# Decide the unit to be used based on the counter.
$unit = $units[min($unitsCount, count($units) - 1)];
# Divide the value by unit size in the power of the counter and round it to keep
# at most the given number of decimal digits.
$value = round($number / pow($unitSize, $unitsCount), $decimals);
# Assemble and return the string.
return $value . $unit;
}
I created my own method inspired by Twitter.
Function:
function legibleNumb($numb, $lang = 'en') {
if ($lang == 'tr') { // Usage with commas in Turkish
if ($numb >= 1000000) { // Million
if (strstr(round(number_format($numb,0,',','.'),1),'.')) {
$legibleNumb = number_format(round(number_format($numb,0,',','.'),1),1,',','.') . ' Mn';
} else {
$legibleNumb = round(number_format($numb,0,',','.'),1) . ' Mn';
}
} elseif ($numb >= 100000 && $numb < 1000000) { // One hundred thousand
$legibleNumb = round(number_format($numb,0,',','.'),0) . ' B';
} elseif ($numb >= 10000 && $numb < 100000) { // Ten thousand
if (strstr(round(number_format($numb,0,',','.'),1),'.')) {
$legibleNumb = number_format(round(number_format($numb,0,',','.'),1),1,',','.') . ' B';
} else {
$legibleNumb = round(number_format($numb,0,',','.'),1) . ' B';
}
} else {
$legibleNumb = number_format($numb,0,',','.');
}
} else { // Dotted usage in English
if ($numb >= 1000000) { // Million
$legibleNumb = round(number_format($numb,0,',','.'),1) . ' M';
} elseif ($numb >= 100000 && $numb < 1000000) { // One hundred thousand
$legibleNumb = round(number_format($numb,0,',','.'),0) . ' K';
} elseif ($numb >= 10000 && $numb < 100000) { // Ten thousand
$legibleNumb = round(number_format($numb,0,',','.'),1) . ' K';
} else {
$legibleNumb = number_format($numb,0,',','.');
}
}
return $legibleNumb;
}
Usage:
echo legibleNumb(9999999,'en');
echo legibleNumb(9999999,'tr');
echo legibleNumb(54669,'en');
echo legibleNumb(54669,'tr');
echo legibleNumb(5466,'en');
echo legibleNumb(5466,'tr');
Results:
10 M
10 Mn
54.7 K
54,7 B
5.466
5.466
You can try it here and check out sample usages: https://glot.io/snippets/eljyd9ssjx
if ($postresultscount > 999999) {
$postresultscount = floor($postresultscount / 1000000) . ' M';
}
elseif ($postresultscount > 999) {
$postresultscount = floor($postresultscount / 1000) . ' K';
}
echo $postresultscount;
This questuion have the same goal as this question in here Shorten long numbers to K/M/B?
Reference:
https://gist.github.com/RadGH/84edff0cc81e6326029c
Try this code:
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;
}
The code above create a function to convert the numbers. To use this function later just call it like in the code below:
// Example Usage:
number_format_short(7201); // Output: 7.2k
Rounding up, not accounting for any abbreviations above 'k' or thousands, showing one decimal place.
function numToKs($number) {
if ($number >= 1000) {
return number_format(($number / 1000), 1) . 'k';
} else {
return $number;
}
}
numToKs(1) = 1
numToKs(111) = 111
numToKs(999) = 999
numToKs(1000) = "1.0k"
numToKs(1499) = "1.5k"
numToKs(1500) = "1.5k"
numToKs(1501) = "1.5k"
numToKs(1550) = "1.6k"
numToKs(11501) = "11.5k"
numToKs(1000000000) = "1,000,000.0k"
numToKs(1234567890) = "1,234,567.9k"