How to set Money Format in PHP - php

I am making real estate portal.In that user has entered property value like
55,00,000 - 45,35,000 - 30,00,000 and so on.
My Question is ,i want to show those values as
55 Lac(s) - 45.35 Lac(s) - 30 Lac(s) so on.So please..suggest me, how can i make this possible.
Thanks

you can use money_format() function in php. http://php.net/manual/en/function.money-format.php
To use money_format() in window, if you have the Intl extension, you can use
http://de.php.net/manual/en/numberformatter.formatcurrency.php— Format a currency value according to the formatter rules.
Example from Manual
$fmt = new NumberFormatter( 'de_DE', NumberFormatter::CURRENCY );
echo $fmt->formatCurrency(1234567.891234567890000, "EUR")."\n";
echo $fmt->formatCurrency(1234567.891234567890000, "RUR")."\n";
$fmt = new NumberFormatter( 'ru_RU', NumberFormatter::CURRENCY );
echo $fmt->formatCurrency(1234567.891234567890000, "EUR")."\n";
echo $fmt->formatCurrency(1234567.891234567890000, "RUR")."\n";
Output
1.234.567,89 €
1.234.567,89 RUR
1 234 567,89€
1 234 567,89р.
Also see my answer on how to parse that formatted money string back into a float:

For normal cases money_format is ideal way to go, But as you require to use a 'Lac' like format. You need to write your own code on conditions basis.
First remove all commas from user entered amount. like that
$number = str_replace(',', '', $number);
Then check and make required string.
if($number > 10000000)
{
$num = ((float)$number) / 10000000;
$num = $num.' Crore(s)'
}
else if($number > 100000)
{
$num = ((float)$number) / 100000;
$num = $num.' Lac(s)'
}
else if($number > 1000)
{
$num = ((float)$number) / 1000;
$num = $num.' Thousand(s)'
}

Look here for Zend Framework
and for core php Here
string money_format ( string $format , float $number )

you can use this function
function formatInCurrencyStyle($num){
$pos = strpos((string)$num, ".");
if ($pos === false) {
$decimalpart="00";
}
if (!($pos === false)) {
$decimalpart= substr($num, $pos+1, 2); $num = substr($num,0,$pos);
}
if(strlen($num)>3 & strlen($num) <= 12){
$last3digits = substr($num, -3 );
$numexceptlastdigits = substr($num, 0, -3 );
$formatted = makeComma($numexceptlastdigits);
$stringtoreturn = $formatted.",".$last3digits.".".$decimalpart ;
}elseif(strlen($num)<=3){
$stringtoreturn = $num.".".$decimalpart ;
}elseif(strlen($num)>12){
$stringtoreturn = number_format($num, 2);
}
if(substr($stringtoreturn,0,2)=="-,"){
$stringtoreturn = "-".substr($stringtoreturn,2 );
}
return $stringtoreturn;
}
function makeComma($input){
if(strlen($input)<=2)
{ return $input; }
$length=substr($input,0,strlen($input)-2);
$formatted_input = makeComma($length).",".substr($input,-2);
return $formatted_input;
}

Use number_format : http://php.net/manual/en/function.number-format.php
$english_format_number = number_format($number, 2, '.', ',');
You can also use money_format : http://php.net/manual/en/function.money-format.php
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.
Note:
The LC_MONETARY category of the locale settings, affects the behavior of this function. Use setlocale() to set to the appropriate default locale before using this function.

just use a simple way
number_format(200000) // 200,000

Related

PHP Remove Unnecessary Zero In Decimals Works, But Not With This Number [duplicate]

I'm trying to find a fast way to remove zero decimals from number values like this:
echo cleanNumber('125.00');
// 125
echo cleanNumber('966.70');
// 966.7
echo cleanNumber(844.011);
// 844.011
Does exists some optimized way to do that?
$num + 0 does the trick.
echo 125.00 + 0; // 125
echo '125.00' + 0; // 125
echo 966.70 + 0; // 966.7
Internally, this is equivalent to casting to float with (float)$num or floatval($num) but I find it simpler.
you could just use the floatval function
echo floatval('125.00');
// 125
echo floatval('966.70');
// 966.7
echo floatval('844.011');
// 844.011
This is what I use:
function TrimTrailingZeroes($nbr) {
return strpos($nbr,'.')!==false ? rtrim(rtrim($nbr,'0'),'.') : $nbr;
}
N.B. This assumes . is the decimal separator. It has the advantage that it will work on arbitrarily large (or small) numbers since there is no float cast. It also won't turn numbers into scientific notation (e.g. 1.0E-17).
If you want to remove the zero digits just before to display on the page or template.
You can use the sprintf() function
sprintf('%g','125.00');
// 125
‌‌sprintf('%g','966.70');
// 966.7
‌‌‌‌sprintf('%g',844.011);
// 844.011
Simply adding + to your string variable will cause typecast to (float) and removes zeros:
var_dump(+'125.00'); // double(125)
var_dump(+'966.70'); // double(966.7)
var_dump(+'844.011'); // double(844.011)
var_dump(+'844.011asdf');// double(844.011)
For everyone coming to this site having the same problem with commata instead, change:
$num = number_format($value, 1, ',', '');
to:
$num = str_replace(',0', '', number_format($value, 1, ',', '')); // e.g. 100,0 becomes 100
If there are two zeros to be removed, then change to:
$num = str_replace(',00', '', number_format($value, 2, ',', '')); // e.g. 100,00 becomes 100
More here: PHP number: decimal point visible only if needed
You should cast your numbers as floats, which will do this for you.
$string = "42.422005000000000000000000000000";
echo (float)$string;
Output of this will be what you are looking for.
42.422005
$x = '100.10';
$x = preg_replace("/\.?0*$/",'',$x);
echo $x;
There is nothing that can't be fixed with a simple regex ;)
http://xkcd.com/208/
Typecast to a float.
$int = 4.324000;
$int = (float) $int;
Be careful with adding +0.
echo number_format(1500.00, 2,".",",")+0;
//1
Result of this is 1.
echo floatval('1,000.00');
// 1
echo floatval('1000.00');
//1000
Sometimes, especially in case of monetary amounts, you want to remove the zeros only if they are 2, you don't want to print € 2.1 instead of € 2.10.
An implementation could be:
function formatAmount(string|float|int $value, int $decimals = 2): string
{
if (floatval(intval($value)) === floatval($value)) {
// The number is an integer. Remove all the decimals
return (string)intval($value);
}
return number_format($value, $decimals);
}
Examples of expected outputs:
0.1000 => 0.10
20.000 => 20
1.25 => 1.25
Example 1
$value =81,500.00;
{{rtrim(rtrim(number_format($value,2),0),'.')}}
output
81,500
Example 2
$value=110,763.14;
{{rtrim(rtrim(number_format($value,2),0),'.')}}
output
110,763.14
Due to this question is old. First, I'm sorry about this.
The question is about number xxx.xx but in case that it is x,xxx.xxxxx or difference decimal separator such as xxxx,xxxx this can be harder to find and remove zero digits from decimal value.
/**
* Remove zero digits (include zero trails - 123.450, 123.000) from decimal value.
*
* #param string|int|float $number The number can be any format, any where use in the world such as 123, 1,234.56, 1234.56789, 12.345,67, -98,765.43
* #param string The decimal separator. You have to set this parameter to exactly what it is. For example: in Europe it is mostly use "," instead of ".".
* #return string Return removed zero digits from decimal value. Only return as string!
*/
function removeZeroDigitsFromDecimal($number, $decimal_sep = '.')
{
$explode_num = explode($decimal_sep, $number);
if (is_countable($explode_num) && count($explode_num) > 1) {
// if exploded number is more than 1 (Example: explode with . for nnnn.nnn is 2)
// replace `is_countable()` with `is_array()` if you are using PHP older than 7.3.
$explode_num[count($explode_num)-1] = preg_replace('/(0+)$/', '', $explode_num[count($explode_num)-1]);
if ($explode_num[count($explode_num)-1] === '') {
// if the decimal value is now empty.
// unset it to prevent nnn. without any number.
unset($explode_num[count($explode_num)-1]);
}
$number = implode($decimal_sep, $explode_num);
}
unset($explode_num);
return (string) $number;
}
And here is the code for test.
$tests = [
1234 => 1234,
-1234 => -1234,
'12,345.67890' => '12,345.6789',
'-12,345,678.901234' => '-12,345,678.901234',
'12345.000000' => '12345',
'-12345.000000' => '-12345',
'12,345.000000' => '12,345',
'-12,345.000000000' => '-12,345',
];
foreach ($tests as $number => $assert) {
$result = removeZeroDigitsFromDecimal($number);
assert($result === (string) $assert, new \Exception($result . ' (' . gettype($result) . ') is not matched ' . $assert . ' (' . gettype($assert) . ')'));
echo $number . ' => ' . (string) $assert . '<br>';
}
echo '<hr>' . PHP_EOL;
$tests = [
1234 => 1234,
-1234 => -1234,
'12.345,67890' => '12.345,6789',
'-12.345.678,901234' => '-12.345.678,901234',
'12345,000000' => '12345',
'-12345,000000' => '-12345',
'-12.345,000000000' => '-12.345',
'-12.345,000000,000' => '-12.345,000000',// this is correct assertion. Weird ,000000,000 but only last 000 will be removed.
];
foreach ($tests as $number => $assert) {
$result = removeZeroDigitsFromDecimal($number, ',');
assert($result === (string) $assert, new \Exception($result . ' (' . gettype($result) . ') is not matched ' . $assert . ' (' . gettype($assert) . ')'));
echo $number . ' => ' . (string) $assert . '<br>';
}
All tests should be pass and no errors.
Why '-12.345,000000,000' will be '-12.345,000000' not '-12.345'?
Because this function is for remove zero digits (include zero trails) from decimal value. It is not validation for the correct number format. That should be another function.
Why always return as string?
Because it is better to use in calculation with bcxxx functions, or use with big number.
$str = 15.00;
$str2 = 14.70;
echo rtrim(rtrim(strval($str), "0"), "."); //15
echo rtrim(rtrim(strval($str2), "0"), "."); //14.7
I found this solution is the best:
public function priceFormat(float $price): string
{
//https://stackoverflow.com/a/14531760/5884988
$price = $price + 0;
$split = explode('.', $price);
return number_format($price, isset($split[1]) ? strlen($split[1]) : 2, ',', '.');
}
The following is much simpler
if(floor($num) == $num) {
echo number_format($num);
} else {
echo $num;
}
You can try the following:
rtrim(number_format($coin->current_price,6),'0.')
Complicated way but works:
$num = '125.0100';
$index = $num[strlen($num)-1];
$i = strlen($num)-1;
while($index == '0') {
if ($num[$i] == '0') {
$num[$i] = '';
$i--;
}
$index = $num[$i];
}
//remove dot if no numbers exist after dot
$explode = explode('.', $num);
if (isset($explode[1]) && intval($explode[1]) <= 0) {
$num = intval($explode[0]);
}
echo $num; //125.01
the solutions above are the optimal way but in case you want to have your own you could use this. What this algorithm does it starts at the end of string and checks if its 0, if it is it sets to empty string and then goes to the next character from back untill the last character is > 0
$value = preg_replace('~\.0+$~','',$value);
You can use:
print (floatval)(number_format( $Value), 2 ) );
Thats my small solution...
Can included to a class and set vars
private $dsepparator = '.'; // decimals
private $tsepparator= ','; // thousand
That can be set by constructor and change to users lang.
class foo
{
private $dsepparator;
private $tsepparator;
function __construct(){
$langDatas = ['en' => ['dsepparator' => '.', 'tsepparator' => ','], 'de' => ['dsepparator' => ',', 'tsepparator' => '.']];
$usersLang = 'de'; // set iso code of lang from user
$this->dsepparator = $langDatas[$usersLang]['dsepparator'];
$this->tsepparator = $langDatas[$usersLang]['tsepparator'];
}
public function numberOmat($amount, $decimals = 2, $hideByZero = false)
{
return ( $hideByZero === true AND ($amount-floor($amount)) <= 0 ) ? number_format($amount, 0, $this->dsepparator, $this->tsepparator) : number_format($amount, $decimals, $this->dsepparator, $this->tsepparator);
}
/*
* $bar = new foo();
* $bar->numberOmat('5.1234', 2, true); // returns: 5,12
* $bar->numberOmat('5', 2); // returns: 5,00
* $bar->numberOmat('5.00', 2, true); // returns: 5
*/
}
This is my solution.
I want to keep ability to add thousands separator
$precision = 5;
$number = round($number, $precision);
$decimals = strlen(substr(strrchr($number, '.'), 1));
return number_format($number, $precision, '.', ',');
This is a simple one line function using rtrim, save separator and decimal point :
function myFormat($num,$dec)
{
return rtrim(rtrim(number_format($num,$dec),'0'),'.');
}
Simple and accurate!
function cleanNumber($num){
$explode = explode('.', $num);
$count = strlen(rtrim($explode[1],'0'));
return bcmul("$num",'1', $count);
}
I use this simple code:
define('DECIMAL_SEPARATOR', ','); //To prove that it works with different separators than "."
$input = "50,00";
$number = rtrim($input, '0'); // 50,00 --> 50,
$number = rtrim($number, DECIMAL_SEPARATOR); // 50, --> 50
echo $number;
Seems a bit too easy to be the really correct solution, but it works just fine for me. You should do some tests with the inputs you'll be getting before using this.
Assuming the amount is a string with 2 decimal places, then you can use:
protected function removeZerosDecimals(string $money): string
{
$formatter = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
$uselessDecimals = sprintf(
'%s00',
$formatter->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL)
);
if (!str_ends_with($money, $uselessDecimals)) {
return $money;
}
$len = mb_strlen($money);
return mb_substr($money, 0, $len - mb_strlen($uselessDecimals));
}
That will work as expected for ?any? currency, like $500.00 and R$ 500,00.
function removeZerosAfterDecimals($number) {
$number = trim($number);
if($number <= 0 || empty($number)) {
return $number;
}
$ary = explode('.', $number);
if(count($ary) <= 1) {
return $number;
}
$reverseAry = array_reverse($ary);
$endSearch = false;
$newNumber = [];
for($i=0; $i<count($reverseAry); $i++) {
if($reverseAry[$i] != 0 && $endSearch === false) {
$newNumber[] = $reverseAry[$i];
$endSearch = true;
} else if ($endSearch === true) {
$newNumber[] = $reverseAry[$i];
}
}
return implode('.',array_reverse($newNumber));
}
//output: 10.0.1.0 => 10.0.1
//output: 10.0.1 => 10.0.1
//output: 10.1.2 => 10.1.2
//output: 10.0.0 => 10
This function will only remove the trailing zero decimals
This Code will remove zero after point and will return only two decimal digits.
$number=1200.0000;
str_replace('.00', '',number_format($number, 2, '.', ''));
Output will be: 1200
Ultimate Solution: The only safe way is to use regex:
echo preg_replace("/\.?0+$/", "", 3.0); // 3
echo preg_replace("/\d+\.?\d*(\.?0+)/", "", 3.0); // 3
it will work for any case

PHP formating numbers to locale and back

After a lot of research I am actually using the following function to format numbers to the locale setted by the user:
function number_format_i18n($number, $decimals=0) {
$locale = localeconv();
return number_format($number,$decimals, $locale['decimal_point'], $locale['thousands_sep']);
}
I'll use this to format numbers from DB.
But if I have a form where a user can enter a number, I need a function to format it back so I can save into the DB. Here I found this solution:
function number_format_en($number) {
// $_SESSION['lang']['locale'] has the locale like de_DE, ar_AE, tr_TR, ...
$fmt = numfmt_create($_SESSION['lang']['locale'], NumberFormatter::DECIMAL);
return numfmt_parse($fmt, $number);
}
This works with the most locales I tested but not with everyone! As an example: if I use arabic (ar_AE):
$randomNumber = 3171003633.95;
$number2locale = number_format_i18n($randomNumber, 2);
// works as expected: 3,171,003,633.95
// now format it back:
$locale2number = number_format_en($number2locale);
// here I get this: 3.171
How can I format a locale entered number in a secure way "back" to en-format? Or is there a way to detect any kind of numberformat and format it to en-format so I can save it in the DB?
So, don't know really if this is a good solution or not - but it seems to be working fine:
function number_format_en($number) {
// first remove everything execpt -,.
$cleanNumber = preg_replace('/[^\\d-,.]+/', '', $number);
$last_dot = strrpos($cleanNumber, '.');
$last_comma = strrpos($cleanNumber, ',');
if($last_dot !== false || $last_comma !== false) {
if($last_dot > $last_comma) { // decimal seperator = dot
$decimal_point = '.';
if(substr_count($cleanNumber, '.') > 1) {
// could be totaly wrong 1,234.567.890
// or there are no decimals 1.234.567.890
// removing all dots and commas and returning the value
return preg_replace('/[^\\d-]+/', '', $cleanNumber);
}
} else { // decimal seperator = comma
$decimal_point = ',';
if(substr_count($cleanNumber, ',') > 1) {
// could be totaly wrong 1.234,567,890
// or there are no decimals 1,234,567,890
// removing all dots and commas and returning the value
return preg_replace('/[^\\d-]+/', '', $cleanNumber);
}
}
} else { // no decimals
$decimal_point = false;
$decimals = 0;
}
if($decimal_point !== false) {
// if decimals are delivered, get the count of them
$length = strlen($cleanNumber);
$position = strpos($cleanNumber, $decimal_point);
$decimals = $length - $position - 1;
if($decimal_point == '.') {
// remove all commas if seperator = .
$cleanNumber = str_replace(',', '', $cleanNumber);
} elseif($decimal_point == ',') {
// remove all dots if seperator = ,
$cleanNumber = str_replace('.', '', $cleanNumber);
// now switch comma with dot
$cleanNumber = str_replace(',', '.', $cleanNumber);
}
}
return $cleanNumber;
}
I'll check the last dot or comma and depending on that I format the number, function returns the same count of decimals as the original number. there is a "known" bug: if someone enters a full number like 1.000.000 or 1,000,000 it returns 1000000.
As an example:
number_format_en('1.234.567,89') // 1234567.89
number_format_en('-1,234,567.89') // -1234567.89
number_format_en('1.234.567.89') // 123456789 (only dots)
number_format_en('1,234,567,89') // 123456789 (only commas)
Would be nice if someone can post a comment if this is a good way or not or an answer with a better solution :)

PHP Number Format (Construction Station)

I'm trying to format construction stationing, but I can't figure out how to get the preg_replace function to accept a variable number of leading characters. The format is [variable leading characters]+XX.XX This is what I'm using right now:
Input:
0
20
160
5005.5
30096.56
1000000000.00
Function:
function formatStation($number){
$number = sprintf('%06.2f', $number);
$number = preg_replace('/([0-9])([0-9]{2})/', '$1+$2', $number);
return $number;
}
Output:
0+00.00
0+20.00
1+60.00
5+005.50 <-
3+0096.56 <-
1+000000000.00 <-
The correct output should be:
0+00.00
0+20.00
1+60.00
50+05.50 <-
300+96.56 <-
10000000+00.00 <-
Here is the code, which work according to your assignment:
function formatStation($number){
$number = sprintf('%06.2f', $number);
$number = preg_replace('/([0-9])([0-9]{2}\.[0-9]{2})/', '$1+$2', $number);
return $number;
}
Here you can test it.
With substr_replace:
function formatStation($number)
{
return substr_replace(sprintf('%06.2f', $number), '+', -5, 0);
}
Since this is based strictly on string position it can also be done without regex using substr.
function formatStation($number){
$n = sprintf('%06.2f', $number);
return substr($n, 0, strlen($n) - 5) . '+' . substr($n, -5);
}

Remove useless zero digits from decimals in PHP

I'm trying to find a fast way to remove zero decimals from number values like this:
echo cleanNumber('125.00');
// 125
echo cleanNumber('966.70');
// 966.7
echo cleanNumber(844.011);
// 844.011
Does exists some optimized way to do that?
$num + 0 does the trick.
echo 125.00 + 0; // 125
echo '125.00' + 0; // 125
echo 966.70 + 0; // 966.7
Internally, this is equivalent to casting to float with (float)$num or floatval($num) but I find it simpler.
you could just use the floatval function
echo floatval('125.00');
// 125
echo floatval('966.70');
// 966.7
echo floatval('844.011');
// 844.011
This is what I use:
function TrimTrailingZeroes($nbr) {
return strpos($nbr,'.')!==false ? rtrim(rtrim($nbr,'0'),'.') : $nbr;
}
N.B. This assumes . is the decimal separator. It has the advantage that it will work on arbitrarily large (or small) numbers since there is no float cast. It also won't turn numbers into scientific notation (e.g. 1.0E-17).
If you want to remove the zero digits just before to display on the page or template.
You can use the sprintf() function
sprintf('%g','125.00');
// 125
‌‌sprintf('%g','966.70');
// 966.7
‌‌‌‌sprintf('%g',844.011);
// 844.011
Simply adding + to your string variable will cause typecast to (float) and removes zeros:
var_dump(+'125.00'); // double(125)
var_dump(+'966.70'); // double(966.7)
var_dump(+'844.011'); // double(844.011)
var_dump(+'844.011asdf');// double(844.011)
For everyone coming to this site having the same problem with commata instead, change:
$num = number_format($value, 1, ',', '');
to:
$num = str_replace(',0', '', number_format($value, 1, ',', '')); // e.g. 100,0 becomes 100
If there are two zeros to be removed, then change to:
$num = str_replace(',00', '', number_format($value, 2, ',', '')); // e.g. 100,00 becomes 100
More here: PHP number: decimal point visible only if needed
You should cast your numbers as floats, which will do this for you.
$string = "42.422005000000000000000000000000";
echo (float)$string;
Output of this will be what you are looking for.
42.422005
$x = '100.10';
$x = preg_replace("/\.?0*$/",'',$x);
echo $x;
There is nothing that can't be fixed with a simple regex ;)
http://xkcd.com/208/
Typecast to a float.
$int = 4.324000;
$int = (float) $int;
Be careful with adding +0.
echo number_format(1500.00, 2,".",",")+0;
//1
Result of this is 1.
echo floatval('1,000.00');
// 1
echo floatval('1000.00');
//1000
Sometimes, especially in case of monetary amounts, you want to remove the zeros only if they are 2, you don't want to print € 2.1 instead of € 2.10.
An implementation could be:
function formatAmount(string|float|int $value, int $decimals = 2): string
{
if (floatval(intval($value)) === floatval($value)) {
// The number is an integer. Remove all the decimals
return (string)intval($value);
}
return number_format($value, $decimals);
}
Examples of expected outputs:
0.1000 => 0.10
20.000 => 20
1.25 => 1.25
Example 1
$value =81,500.00;
{{rtrim(rtrim(number_format($value,2),0),'.')}}
output
81,500
Example 2
$value=110,763.14;
{{rtrim(rtrim(number_format($value,2),0),'.')}}
output
110,763.14
Due to this question is old. First, I'm sorry about this.
The question is about number xxx.xx but in case that it is x,xxx.xxxxx or difference decimal separator such as xxxx,xxxx this can be harder to find and remove zero digits from decimal value.
/**
* Remove zero digits (include zero trails - 123.450, 123.000) from decimal value.
*
* #param string|int|float $number The number can be any format, any where use in the world such as 123, 1,234.56, 1234.56789, 12.345,67, -98,765.43
* #param string The decimal separator. You have to set this parameter to exactly what it is. For example: in Europe it is mostly use "," instead of ".".
* #return string Return removed zero digits from decimal value. Only return as string!
*/
function removeZeroDigitsFromDecimal($number, $decimal_sep = '.')
{
$explode_num = explode($decimal_sep, $number);
if (is_countable($explode_num) && count($explode_num) > 1) {
// if exploded number is more than 1 (Example: explode with . for nnnn.nnn is 2)
// replace `is_countable()` with `is_array()` if you are using PHP older than 7.3.
$explode_num[count($explode_num)-1] = preg_replace('/(0+)$/', '', $explode_num[count($explode_num)-1]);
if ($explode_num[count($explode_num)-1] === '') {
// if the decimal value is now empty.
// unset it to prevent nnn. without any number.
unset($explode_num[count($explode_num)-1]);
}
$number = implode($decimal_sep, $explode_num);
}
unset($explode_num);
return (string) $number;
}
And here is the code for test.
$tests = [
1234 => 1234,
-1234 => -1234,
'12,345.67890' => '12,345.6789',
'-12,345,678.901234' => '-12,345,678.901234',
'12345.000000' => '12345',
'-12345.000000' => '-12345',
'12,345.000000' => '12,345',
'-12,345.000000000' => '-12,345',
];
foreach ($tests as $number => $assert) {
$result = removeZeroDigitsFromDecimal($number);
assert($result === (string) $assert, new \Exception($result . ' (' . gettype($result) . ') is not matched ' . $assert . ' (' . gettype($assert) . ')'));
echo $number . ' => ' . (string) $assert . '<br>';
}
echo '<hr>' . PHP_EOL;
$tests = [
1234 => 1234,
-1234 => -1234,
'12.345,67890' => '12.345,6789',
'-12.345.678,901234' => '-12.345.678,901234',
'12345,000000' => '12345',
'-12345,000000' => '-12345',
'-12.345,000000000' => '-12.345',
'-12.345,000000,000' => '-12.345,000000',// this is correct assertion. Weird ,000000,000 but only last 000 will be removed.
];
foreach ($tests as $number => $assert) {
$result = removeZeroDigitsFromDecimal($number, ',');
assert($result === (string) $assert, new \Exception($result . ' (' . gettype($result) . ') is not matched ' . $assert . ' (' . gettype($assert) . ')'));
echo $number . ' => ' . (string) $assert . '<br>';
}
All tests should be pass and no errors.
Why '-12.345,000000,000' will be '-12.345,000000' not '-12.345'?
Because this function is for remove zero digits (include zero trails) from decimal value. It is not validation for the correct number format. That should be another function.
Why always return as string?
Because it is better to use in calculation with bcxxx functions, or use with big number.
$str = 15.00;
$str2 = 14.70;
echo rtrim(rtrim(strval($str), "0"), "."); //15
echo rtrim(rtrim(strval($str2), "0"), "."); //14.7
I found this solution is the best:
public function priceFormat(float $price): string
{
//https://stackoverflow.com/a/14531760/5884988
$price = $price + 0;
$split = explode('.', $price);
return number_format($price, isset($split[1]) ? strlen($split[1]) : 2, ',', '.');
}
The following is much simpler
if(floor($num) == $num) {
echo number_format($num);
} else {
echo $num;
}
You can try the following:
rtrim(number_format($coin->current_price,6),'0.')
Complicated way but works:
$num = '125.0100';
$index = $num[strlen($num)-1];
$i = strlen($num)-1;
while($index == '0') {
if ($num[$i] == '0') {
$num[$i] = '';
$i--;
}
$index = $num[$i];
}
//remove dot if no numbers exist after dot
$explode = explode('.', $num);
if (isset($explode[1]) && intval($explode[1]) <= 0) {
$num = intval($explode[0]);
}
echo $num; //125.01
the solutions above are the optimal way but in case you want to have your own you could use this. What this algorithm does it starts at the end of string and checks if its 0, if it is it sets to empty string and then goes to the next character from back untill the last character is > 0
$value = preg_replace('~\.0+$~','',$value);
You can use:
print (floatval)(number_format( $Value), 2 ) );
Thats my small solution...
Can included to a class and set vars
private $dsepparator = '.'; // decimals
private $tsepparator= ','; // thousand
That can be set by constructor and change to users lang.
class foo
{
private $dsepparator;
private $tsepparator;
function __construct(){
$langDatas = ['en' => ['dsepparator' => '.', 'tsepparator' => ','], 'de' => ['dsepparator' => ',', 'tsepparator' => '.']];
$usersLang = 'de'; // set iso code of lang from user
$this->dsepparator = $langDatas[$usersLang]['dsepparator'];
$this->tsepparator = $langDatas[$usersLang]['tsepparator'];
}
public function numberOmat($amount, $decimals = 2, $hideByZero = false)
{
return ( $hideByZero === true AND ($amount-floor($amount)) <= 0 ) ? number_format($amount, 0, $this->dsepparator, $this->tsepparator) : number_format($amount, $decimals, $this->dsepparator, $this->tsepparator);
}
/*
* $bar = new foo();
* $bar->numberOmat('5.1234', 2, true); // returns: 5,12
* $bar->numberOmat('5', 2); // returns: 5,00
* $bar->numberOmat('5.00', 2, true); // returns: 5
*/
}
This is my solution.
I want to keep ability to add thousands separator
$precision = 5;
$number = round($number, $precision);
$decimals = strlen(substr(strrchr($number, '.'), 1));
return number_format($number, $precision, '.', ',');
This is a simple one line function using rtrim, save separator and decimal point :
function myFormat($num,$dec)
{
return rtrim(rtrim(number_format($num,$dec),'0'),'.');
}
Simple and accurate!
function cleanNumber($num){
$explode = explode('.', $num);
$count = strlen(rtrim($explode[1],'0'));
return bcmul("$num",'1', $count);
}
I use this simple code:
define('DECIMAL_SEPARATOR', ','); //To prove that it works with different separators than "."
$input = "50,00";
$number = rtrim($input, '0'); // 50,00 --> 50,
$number = rtrim($number, DECIMAL_SEPARATOR); // 50, --> 50
echo $number;
Seems a bit too easy to be the really correct solution, but it works just fine for me. You should do some tests with the inputs you'll be getting before using this.
Assuming the amount is a string with 2 decimal places, then you can use:
protected function removeZerosDecimals(string $money): string
{
$formatter = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
$uselessDecimals = sprintf(
'%s00',
$formatter->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL)
);
if (!str_ends_with($money, $uselessDecimals)) {
return $money;
}
$len = mb_strlen($money);
return mb_substr($money, 0, $len - mb_strlen($uselessDecimals));
}
That will work as expected for ?any? currency, like $500.00 and R$ 500,00.
function removeZerosAfterDecimals($number) {
$number = trim($number);
if($number <= 0 || empty($number)) {
return $number;
}
$ary = explode('.', $number);
if(count($ary) <= 1) {
return $number;
}
$reverseAry = array_reverse($ary);
$endSearch = false;
$newNumber = [];
for($i=0; $i<count($reverseAry); $i++) {
if($reverseAry[$i] != 0 && $endSearch === false) {
$newNumber[] = $reverseAry[$i];
$endSearch = true;
} else if ($endSearch === true) {
$newNumber[] = $reverseAry[$i];
}
}
return implode('.',array_reverse($newNumber));
}
//output: 10.0.1.0 => 10.0.1
//output: 10.0.1 => 10.0.1
//output: 10.1.2 => 10.1.2
//output: 10.0.0 => 10
This function will only remove the trailing zero decimals
This Code will remove zero after point and will return only two decimal digits.
$number=1200.0000;
str_replace('.00', '',number_format($number, 2, '.', ''));
Output will be: 1200
Ultimate Solution: The only safe way is to use regex:
echo preg_replace("/\.?0+$/", "", 3.0); // 3
echo preg_replace("/\d+\.?\d*(\.?0+)/", "", 3.0); // 3
it will work for any case

masking credit card & bank account information

I'm looking for a php function which can mask credit card & bank information such as routing number and account numbers. I need to mask many formats, so the existing stack overflow answers don't help me that much.
So for example, if the input is 304-443-2456, the function should return xxx-xxx-2456.
Sometimes the number has dashes, and can be in various lengths.
I'm looking for something generic, that I can extend as needed, preferably a zend framework view helper class.
Some little regex in a function of it own, configuration available:
$number = '304-443-2456';
function mask_number($number, $count = 4, $seperators = '-')
{
$masked = preg_replace('/\d/', 'x', $number);
$last = preg_match(sprintf('/([%s]?\d){%d}$/', preg_quote($seperators), $count), $number, $matches);
if ($last) {
list($clean) = $matches;
$masked = substr($masked, 0, -strlen($clean)) . $clean;
}
return $masked;
}
echo mask_number($number); # xxx-xxx-2456
If the function fails, it will return all masked (e.g. a different seperator, less than 4 digits etc.). Some child-safety build in you could say.
Demo
<?php
function ccmask($cc, $char = '#') {
$pattern = '/^([0-9-]+)([0-9]*)$/U';
$matches = array();
preg_match($pattern, $cc, $matches);
return preg_replace('([0-9])', $char, $matches[1]).$matches[2];
}
echo ccmask('304-443-2456'), "\n";
echo ccmask('4924-7921-9900-9876', '*'), "\n";
echo ccmask('30-43-56', 'x'), "\n";
Outputs:
###-###-2456
****-****-****-9876
xx-xx-56
I use a view helper for that. I tend to avoid Regex though as it always takes me ages to work out what it does, especially if I come back to code after a while.
class Zend_View_Helper_Ccmask
{
public function ccmask($ccNum)
{
$maskArray = explode('-', $ccNum);
$sections = count($maskArray) - 1;
for($i = 0; $i < $sections ; $i++){
$maskArray[$i] = str_replace(array(1,2,3,4,5,6,7,8,9,0), 'x', $maskArray[$i]);
}
return implode('-', $maskArray);
}
}
In your view
echo $this->ccmask('304-443-2456');
//output = xxx-xxx-2456
A good way to look at this is at what won't be masked and outputing xs for everything else. A simple, inexpensive solution is:
function cc_mask( $cc_raw, $unmask_count ){
$cc_masked = '';
for( $i=0; $i < ( strlen( $cc_raw ) - $unmask_count ) ; $i++ ){
//If you want to maintain hyphens and special characters
$char = substr( $cc_raw, $i, 1 );
$cc_masked .= ctype_digit( $char ) ? "*" : $char;
}
$cc_masked .= substr( $cc_raw , -$unmask_count );
return $cc_masked;
}
echo cc_mask("304-443-2456",4);
//Output
***-***-2456
Would be even faster if there was no need to maintain the hyphens and special characters

Categories