Hi,
For South Asian Currencies, this function could be a handy one.
It will handle negative as well as float(Paise).
<?php
function my_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));
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);
}
return $negative.$formatted_rupee.$formatted_paise;
}
?>
Thanks,
money_format
(PHP 4 >= 4.3.0, PHP 5)
money_format — Форматира число като парична величина
Описание
money_format() връща форматирана версия на number . Тази функция е обвивка на функцията strfmon() от библиотеката на езика C, с тази разлика, че текущата имплементация преобразува само по едно число в даден момент.
Параметри
- format
-
Спецификцията на формата се състои от:
символа %
незадължителни флагове
незадължителна ширина на полето
незадължителна точност до десетичната запетая
незадължителна точност след десетичната запетая
задължителен знак за преобразуване
Флагове
Могат да бъдат използвани един или повече от незадължителните флагове използвани по-долу:
- =f
-
Знакът = последван от друг знак f задава знака за допълване. По подразбиране знакът за допълване е интервал.
- ^
-
Забранява използването на групиращи знаци (съгласно текущия локал).
- + или (
-
Указва, стила на форматиране на положителни и отрицателни числа. Ако се използва +, ще се използват еквивалентните стойности за + и - на базата на локала. Ако се използва (, отрицателните стойности ще бъдат оградени с кръгли скоби. Ако не е указано нищо, за стойност по подразбиране се приема +.
- !
-
Премахва текущият символ от низа за извеждане.
- -
-
Ако този флаг е зададен, всички полета ще бъдат подравнени в ляво (със свободно място в дясно), противно на състоянието по подразбиране при което полетата са подравнени в дясно (със свободно място в ляво).
Ширина на полета
- w
-
Низ от десетични цивфи, задаващ минималната ширина на полето. Ако не е указан флага -, полето ще бъде подравнено в дясно. Стойността му по подразбиране е 0 (нула).
Точност до запетаята
- #n
-
Максималния брой цифри (n) до десетичния знак (например десетична запетая). Обикновено се използва за да се запаси подравняването на изхода в еднакви колони, използвайки знак за допълване, ако числата са по-малко на брой от n. Ако броят на цифрите е по-голям от n, този параметър се игнорира.
Ако групирането не е забранено с флага ^, груповите разделители ще бъдат вмъкнати преди знаците за допълване да се добавят (ако съществуват такива). Груповите разделители няма да бъдат приложени към допълващите знаци, дори и ако допълващият знак е цифра.
За осигуряване на подравняването, всеки знак преди и след числото във форматирания изход, като например знак за валута или символи за положителни или отрицателни числа се уплътняват при необходимост чрез интервали, с цел резултата от форматирането на положителните и отрицателните числа да има една и съща дължина.
Точност след запетаята
- .p
-
Точка, след която има последователност от знаци (p) след символа за десетична запетая. Ако стойността на p е 0 (нула), символа за десетична запетая и знаците след него няма да бъдат изведени. Ако не е указана точност след десетичната запетая, стойността по подразбиране ще зависи от текущия локал. Преди форматирането, числото се закръгля до указаното количество знаци.
Знаци за преобразуването
- i
-
Числото се форматира съгласно международния формат на валутата на текущия локал (например за локала на САЩ: USD 1,234.56).
- n
-
Числото се форматира съгласно националния формат на валутата на текущия локал (например за de_DE локал: DM1.234,56).
- %
-
Връща знака %.
- number
-
Числото, което трябва да се форматира.
Връщани стойности
Връща форматираният низ. Знаците преди и след форматирания низ ще бъдат върнати непроменени. Ако параметърът number не е число, функцията ще върне стойност NULL и ще генерира E_WARNING.
Бележки
Забележка: Функция money_format() е дефинирана само, ако системата поддръжа strfmon. Например, при Windows нямаме такава поддръжка, така че, функцията там не е дефинирана.
Забележка: Категория LC_MONETARY от настройките на локала, влиеяе на поведението на тази функция. Използвайте setlocale() за да установите съответния локал по подразбиране преди да използвате функцията.
Примери
Example #1 Пример за money_format()
Ще използваме различни локали и форматирания, за да илюстрираме употребата на тази функция.
<?php
$number = 1234.56;
// нека изведем международния формат за локал en_US
setlocale(LC_MONETARY, 'en_US');
echo money_format('%i', $number) . "\n";
// USD 1,234.56
// Италианският национален формат с 2 знака след запетаята`
setlocale(LC_MONETARY, 'it_IT');
echo money_format('%.2n', $number) . "\n";
// L. 1.234,56
// Използване на отрицателно число
$number = -1234.5672;
// Националният формат на САЩ с използване на скоби за
// отрицателни числа и 10 знака до десетичната запетая
setlocale(LC_MONETARY, 'en_US');
echo money_format('%(#10n', $number) . "\n";
// ($ 1,234.57)
// Подобен формат като горния, но с добавени 2 знака към
// точността след десетичната запетая и '*' като знак за допълване.
echo money_format('%=*(#10.2n', $number) . "\n";
// ($********1,234.57)
// Нека го подравним в ляво, с ширина 14 знака, 8 знака точност
// след преди десетичната запетая, 2 знака точност след десетичната
// запетая, без знак за групиране и посредством използване на
// международния формат на локал de_DE.
setlocale(LC_MONETARY, 'de_DE');
echo money_format('%=*^-14#8.2i', 1234.56) . "\n";
// DEM 1234,56****
// Нека добавим малко текст преди и след описанието на формата
setlocale(LC_MONETARY, 'en_GB');
$fmt = 'Крайната цена е %i (след 10%% намаление)';
echo money_format($fmt, 1234.56) . "\n";
// Крайната цена е GBP 1,234.56 (след 10% намаление)
?>
Вж. също
- setlocale() - Установява локал
- sscanf() - Прави разбор на низ в съответствие със зададен формат
- sprintf() - Връща форматиран низ
- printf() - Извежда форматиран низ
- number_format() - Форматира число с групиране на хилядите
This function divides integer value by commas. F.e.
<?php
echo formatMoney(1050); # 1,050
echo formatMoney(1321435.4, true); # 1,321,435.40
echo formatMoney(10059240.42941, true); # 10,059,240.43
echo formatMoney(13245); # 13,245
function formatMoney($number, $fractional=false) {
if ($fractional) {
$number = sprintf('%.2f', $number);
}
while (true) {
$replaced = preg_replace('/(-?\d+)(\d\d\d)/', '$1,$2', $number);
if ($replaced != $number) {
$number = $replaced;
} else {
break;
}
}
return $number;
}
?>
This is a some function posted before, however various bugs were corrected.
Thank you to Stuart Roe by reporting the bug on printing signals.
<?php
/*
That it is an implementation of the function money_format for the
platforms that do not it bear.
The function accepts to same string of format accepts for the
original function of the PHP.
(Sorry. my writing in English is very bad)
The function is tested using PHP 5.1.4 in Windows XP
and Apache WebServer.
*/
function money_format($format, $number)
{
$regex = '/%((?:[\^!\-]|\+|\(|\=.)*)([0-9]+)?'.
'(?:#([0-9]+))?(?:\.([0-9]+))?([in%])/';
if (setlocale(LC_MONETARY, 0) == 'C') {
setlocale(LC_MONETARY, '');
}
$locale = localeconv();
preg_match_all($regex, $format, $matches, PREG_SET_ORDER);
foreach ($matches as $fmatch) {
$value = floatval($number);
$flags = array(
'fillchar' => preg_match('/\=(.)/', $fmatch[1], $match) ?
$match[1] : ' ',
'nogroup' => preg_match('/\^/', $fmatch[1]) > 0,
'usesignal' => preg_match('/\+|\(/', $fmatch[1], $match) ?
$match[0] : '+',
'nosimbol' => preg_match('/\!/', $fmatch[1]) > 0,
'isleft' => preg_match('/\-/', $fmatch[1]) > 0
);
$width = trim($fmatch[2]) ? (int)$fmatch[2] : 0;
$left = trim($fmatch[3]) ? (int)$fmatch[3] : 0;
$right = trim($fmatch[4]) ? (int)$fmatch[4] : $locale['int_frac_digits'];
$conversion = $fmatch[5];
$positive = true;
if ($value < 0) {
$positive = false;
$value *= -1;
}
$letter = $positive ? 'p' : 'n';
$prefix = $suffix = $cprefix = $csuffix = $signal = '';
$signal = $positive ? $locale['positive_sign'] : $locale['negative_sign'];
switch (true) {
case $locale["{$letter}_sign_posn"] == 1 && $flags['usesignal'] == '+':
$prefix = $signal;
break;
case $locale["{$letter}_sign_posn"] == 2 && $flags['usesignal'] == '+':
$suffix = $signal;
break;
case $locale["{$letter}_sign_posn"] == 3 && $flags['usesignal'] == '+':
$cprefix = $signal;
break;
case $locale["{$letter}_sign_posn"] == 4 && $flags['usesignal'] == '+':
$csuffix = $signal;
break;
case $flags['usesignal'] == '(':
case $locale["{$letter}_sign_posn"] == 0:
$prefix = '(';
$suffix = ')';
break;
}
if (!$flags['nosimbol']) {
$currency = $cprefix .
($conversion == 'i' ? $locale['int_curr_symbol'] : $locale['currency_symbol']) .
$csuffix;
} else {
$currency = '';
}
$space = $locale["{$letter}_sep_by_space"] ? ' ' : '';
$value = number_format($value, $right, $locale['mon_decimal_point'],
$flags['nogroup'] ? '' : $locale['mon_thousands_sep']);
$value = @explode($locale['mon_decimal_point'], $value);
$n = strlen($prefix) + strlen($currency) + strlen($value[0]);
if ($left > 0 && $left > $n) {
$value[0] = str_repeat($flags['fillchar'], $left - $n) . $value[0];
}
$value = implode($locale['mon_decimal_point'], $value);
if ($locale["{$letter}_cs_precedes"]) {
$value = $prefix . $currency . $space . $value . $suffix;
} else {
$value = $prefix . $value . $space . $currency . $suffix;
}
if ($width > 0) {
$value = str_pad($value, $width, $flags['fillchar'], $flags['isleft'] ?
STR_PAD_RIGHT : STR_PAD_LEFT);
}
$format = str_replace($fmatch[0], $value, $format);
}
return $format;
}
?>
If money_format doesn't seem to be working properly, make sure you are defining a valid locale. For example, on Debian, 'en_US' is not a valid locale - you need 'en_US.UTF-8' or 'en_US.ISO-8559-1'.
This was frustrating me for a while. Debian has a list of valid locales at /usr/share/i18n/SUPPORTED; find yours there if it's not working properly.
Consider formatting currency for some South Asian countries that use ##,##,###.## money format.
The following code generates something like Rs. 4,54,234.00 and so on.
<?php
function convertcash($num, $currency){
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++){
$explrestunits .= (int)$expunit[$i].","; // creates each of the 2's group and adds a comma to the end
}
$thecash = $explrestunits.$lastthree;
} else {
$thecash = $convertnum;
}
return $currency.$thecash.".00"; // writes the final format where $currency is the currency symbol.
}
?>
now call the function as convertcash($row['price'], 'Rs '); // that's the price from the database I called using an Indian Rupees prefix where the price has to be a plain number format, say something like 454234.
This is a handy little bit of code I just wrote, as I was not able to find anything else suitable for my situation.
This will handle monetary values that are passed to the script by a user, to reformat any comma use so that it is not broken when it passes through an input validation system that checks for a float.
It is not foolproof, but will handle the common input as most users would input it, such as 1,234,567 (outputs 1234567) or 1,234.00 (outputs 1234.00), even handles 12,34 (outputs 12.34), I expect it would work with negative numbers, but have not tested it, as it is not used for that in my situation.
This worked when other options such as money_format() were not suitable or possible.
<?php
///////////////
// BEGIN CODE convert all price amounts into well formatted values
function converttonum($convertnum,$fieldinput){
$bits = explode(",",$convertnum); // split input value up to allow checking
$first = strlen($bits[0]); // gets part before first comma (thousands/millions)
$last = strlen($bits[1]); // gets part after first comma (thousands (or decimals if incorrectly used by user)
if ($last <3){ // checks for comma being used as decimal place
$convertnum = str_replace(",",".",$convertnum);
}
else{ // assume comma is a thousands seperator, so remove it
$convertnum = str_replace(",","",$convertnum);
}
$_POST[$fieldinput] = $convertnum; // redefine the vlaue of the variable, to be the new corrected one
}
@converttonum($_POST[inputone],"inputone");
@converttonum($_POST[inputtwo],"inputtwo");
@converttonum($_POST[inputthree],"inputthree");
// END CODE
//////////////
?>
This is suitable for the English usage, it may need tweaking to work with other types.
Double check that money_format() is defined on any version of PHP you plan your code to run on. You might be surprised.
For example, it worked on my Linux box where I code, but not on servers running BSD 4.11 variants. (This is presumably because strfmon is not defined - see note at the top of teis page). It's not just a windows/unix issue.
