As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
I need to convert say $89.50 to Eighty-Nine Dollars and Fifty Cents using PHP. Is there a function I'm missing somewhere?
Here's a start for you. It's a recursive function I wrote a while back (part of solving a Project Euler problem 17) that converts numbers to letters... It can handle some pretty big numbers ;)
All you need to do is add the dollars and cents components and modify according to need. So basically you'd have to call the function once for the dollar amount and once for the cents component. I don't think there's a native PHP funciton for this. You'd have to use a library (like Pear) function.
(You can see the function in action):
<?php
function translateToWords($number)
{
/*****
* A recursive function to turn digits into words
* Numbers must be integers from -999,999,999,999 to 999,999,999,999 inclussive.
*
* (C) 2010 Peter Ajtai
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* See the GNU General Public License: <http://www.gnu.org/licenses/>.
*
*/
// zero is a special case, it cause problems even with typecasting if we don't deal with it here
$max_size = pow(10,18);
if (!$number) return "zero";
if (is_int($number) && $number < abs($max_size))
{
switch ($number)
{
// set up some rules for converting digits to words
case $number < 0:
$prefix = "negative";
$suffix = translateToWords(-1*$number);
$string = $prefix . " " . $suffix;
break;
case 1:
$string = "one";
break;
case 2:
$string = "two";
break;
case 3:
$string = "three";
break;
case 4:
$string = "four";
break;
case 5:
$string = "five";
break;
case 6:
$string = "six";
break;
case 7:
$string = "seven";
break;
case 8:
$string = "eight";
break;
case 9:
$string = "nine";
break;
case 10:
$string = "ten";
break;
case 11:
$string = "eleven";
break;
case 12:
$string = "twelve";
break;
case 13:
$string = "thirteen";
break;
// fourteen handled later
case 15:
$string = "fifteen";
break;
case $number < 20:
$string = translateToWords($number%10);
// eighteen only has one "t"
if ($number == 18)
{
$suffix = "een";
} else
{
$suffix = "teen";
}
$string .= $suffix;
break;
case 20:
$string = "twenty";
break;
case 30:
$string = "thirty";
break;
case 40:
$string = "forty";
break;
case 50:
$string = "fifty";
break;
case 60:
$string = "sixty";
break;
case 70:
$string = "seventy";
break;
case 80:
$string = "eighty";
break;
case 90:
$string = "ninety";
break;
case $number < 100:
$prefix = translateToWords($number-$number%10);
$suffix = translateToWords($number%10);
$string = $prefix . "-" . $suffix;
break;
// handles all number 100 to 999
case $number < pow(10,3):
// floor return a float not an integer
$prefix = translateToWords(intval(floor($number/pow(10,2)))) . " hundred";
if ($number%pow(10,2)) $suffix = " and " . translateToWords($number%pow(10,2));
$string = $prefix . $suffix;
break;
case $number < pow(10,6):
// floor return a float not an integer
$prefix = translateToWords(intval(floor($number/pow(10,3)))) . " thousand";
if ($number%pow(10,3)) $suffix = translateToWords($number%pow(10,3));
$string = $prefix . " " . $suffix;
break;
case $number < pow(10,9):
// floor return a float not an integer
$prefix = translateToWords(intval(floor($number/pow(10,6)))) . " million";
if ($number%pow(10,6)) $suffix = translateToWords($number%pow(10,6));
$string = $prefix . " " . $suffix;
break;
case $number < pow(10,12):
// floor return a float not an integer
$prefix = translateToWords(intval(floor($number/pow(10,9)))) . " billion";
if ($number%pow(10,9)) $suffix = translateToWords($number%pow(10,9));
$string = $prefix . " " . $suffix;
break;
case $number < pow(10,15):
// floor return a float not an integer
$prefix = translateToWords(intval(floor($number/pow(10,12)))) . " trillion";
if ($number%pow(10,12)) $suffix = translateToWords($number%pow(10,12));
$string = $prefix . " " . $suffix;
break;
// Be careful not to pass default formatted numbers in the quadrillions+ into this function
// Default formatting is float and causes errors
case $number < pow(10,18):
// floor return a float not an integer
$prefix = translateToWords(intval(floor($number/pow(10,15)))) . " quadrillion";
if ($number%pow(10,15)) $suffix = translateToWords($number%pow(10,15));
$string = $prefix . " " . $suffix;
break;
}
} else
{
echo "ERROR with - $number<br/> Number must be an integer between -" . number_format($max_size, 0, ".", ",") . " and " . number_format($max_size, 0, ".", ",") . " exclussive.";
}
return $string;
}
?>
http://pear.php.net/package-info.php?package=Numbers_Words
Because clearly "no" wasn't the right answer to this question.
» Summary
The PEAR Numbers_Words
package provides methods for spelling
numerals in words.
No, I believe you need to write one yourself. It's quite straightforward to implement but there are a bunch of corner cases you'll need to handle.
No, there is no such function in PHP. The easiest is if you download some code from the internet.
Related
I have a string (trimmed) and I would like to split this string according to a predefined pattern. I wrote a code which is probably more interpretive.
$string="123456789";
$format=['XXX','XX','XXXX'];
$formatted="";
foreach ($format as $cluster){
$formattedCluster=substr($string,0,strlen($cluster));
$string=substr($string,strlen($cluster));
$formatted.=$formattedCluster.' ';
}
$formatted=substr($formatted, 0, -1);
dd($formatted);
//outputs: "123 45 6789"
As you can see it takes a string without any whitespace, and separates it with whitespaces according to a pattern $format in this case. The pattern is an array.
A pseudo example:
$str='qweasdzxc'
$pattern=['X','X','XXXX','XXX']
$formatted='q w easd zxc'; //expected output
It works as expected but it is rather hideous. What is the correct solution to this problem? By correctness, I mean speed and readability.
Environment:
Php 7.4,
Laravel 8
I would use https://www.php.net/manual/en/function.vsprintf.php do get the result:
$str='qweasdzxc';
$pattern='% % %%%% %%%'; // ['X','X','XXXX','XXX']
echo vsprintf(str_replace('%', '%s', $pattern), str_split($str));
$string = "qweasdzxc";
$chunks = array(1,1,4,3);
// Optional check to ensure that $string can be divided into requested chunks
if(array_sum($chunks) <> strlen($string)) {
echo "String length does not fit requested chunks.";
}
$i=0;
$output = "";
foreach($chunks as $chunk) {
$output .= substr($string,$i,$chunk) . " ";
$i += $chunk;
}
echo rtrim($output);
// Outputs "q w easd zxc"
Probably an easier way to remove the whitespace from the right hand end by not adding it in the first place based on whether or not it's the last element of the array, but that does the trick.
easy way to use preg_match try this.
$data = '11234567890';
if(preg_match( '/^\d(\d{3})(\d{3})(\d{4})$/', $data, $matches))
{
$result = $matches[1] . ' ' .$matches[2] . ' ' . $matches[3];
echo $result;
}
I don't think it's what you expected but:
function format_number($number) {
$number_size = strlen($number);
if (9 != $number_size) {
return $number;
}
$step = 0;
$formated = '';
foreach (range(0, 9) as $i => $n) {
if (isset($number[$n])) {
switch ($step) {
case 0:
case 1:
case 3:
case 5:
case 6:
case 7:
case 8:
$formated .= $number[$n];
break;
case 2:
case 4:
$formated .= $number[$n] . ' ';
break;
}
$step++;
}
}
return $formated;
}
Working only for the pattern XXX XX XXXX
I want to convert the integer value to Indian Numbering system. I am giving the value 540000 as input and getting the output value 5.4 Lac, but I want answer 5.40 Lac.
My Code:
<?php
function no_to_words($no)
{
if($no == 0) {
return ' ';
}else {
$n = strlen($no); // 7
switch ($n) {
case 3:
$val = $no/100;
$val = round($val, 2);
$finalval = $val ." Hundred";
break;
case 4:
$val = $no/1000;
$val = round($val, 2);
$finalval = $val ." Thousand";
break;
case 5:
$val = $no/1000;
$val = round($val, 2);
$finalval = $val ." Thousand";
break;
case 6:
$val = $no/100000;
$val = round($val, 2);
$finalval = $val ." Lac";
break;
case 7:
$val = $no/100000;
$val = round($val, 2);
$finalval = $val ." Lac";
break;
case 8:
$val = $no/10000000;
$val = round($val, 2);
$finalval = $val ." Cr";
break;
case 9:
$val = $no/10000000;
$val = round($val, 2);
$finalval = $val ." Cr";
break;
default:
echo "";
}
return $finalval;
}
}
?>
Your problem isn't really this function, since numbers 5.4 and 5.40 are the same number, so either you need to apply formatting here, or in the place where you're using the results. Check the difference of these 2:
echo round(540000/100000, 2);
vs
echo sprintf("%2.2f", round(540000/100000, 2));
The second one will show 2 decimals, since that's defined in the format. You don't really need the round either if you use sprintf, it will round the number to the specified format.
echo sprintf("%2.2f", 555555 / 100000);
this could help what you are expecting.
number_format($val/10000000,2); //for Crore convertion
see my code below
$rand1 = rand(0,9);
$rand2 = rand(0,9);
$operator = array('*','/','+','-');
$randoperator = $operator[rand(0,3)];
$finaalvalue = $rand1."$randoperator".$rand2;
echo $rand1.$randoperator.$rand2.'='.$finaalvalue;
i want to take two random number and do random operation like +,-,*,/ and get their value
like 2-5=6
there is some problem while doing is what am i missing
The obvious answer is to use the eval function, but its use is highly discouraged:
Caution The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is
discouraged. If you have carefully verified that there is no other
option than to use this construct, pay special attention not to pass
any user provided data into it without properly validating it
beforehand.
The other option is to write separate blocks of code that perform the desired operation, then choose the appropriate branch, for example, by using a switch...case statement:
<?php
$rand1 = rand(0, 9);
$rand2 = rand(0, 9);
$operator = array('*', '/', '+', '-');
$randoperator = $operator[rand(0, 3)];
switch ($randoperator) {
case "+":
$finaalvalue = $rand1 + $rand2;
break;
case "-":
$finaalvalue = $rand1 - $rand2;
break;
case "*":
$finaalvalue = $rand1 * $rand2;
break;
case "/":
$finaalvalue = $rand1 / $rand2;
break;
}
echo $rand1 . $randoperator . $rand2 . '=' . $finaalvalue;
if I'm reading your question right, you're computing a string, not applying the operator. You must apply code to rand1 and rand2 to compute the final value.
The easy way is to eval $finaalvalue ($finalvaalue = eval("return $finaalvalue ;");) before echoing it.
If you need the code to run fast, or don't trust the input, use a switch or a function map:
$operatorMap = array(
'+' => function($a, $b) { return $a + $b; },
'*' => function($a, $b) { return $a * $b; },
...
);
$finaalvalue = $operatorMap[$operator]($rand1, $rand2);
PHP anonymous functions run slow compared to methods and normal functions, so avoid them in tight loops where speed matters.
Is this a homework question? You should do your own work.
This should work for you:
(Also if you do random calculation's you would have to check that there is no division by zero)
<?php
function calculate_string( $mathString ) {
$mathString = trim($mathString);
$mathString = str_replace ('[^0-9\+-\*\/\(\) ]', '', $mathString);
$compute = create_function("", "return (" . $mathString . ");" );
return 0 + $compute();
}
$rand1 = rand(0,9);
$rand2 = rand(0,9);
$operator = array('*','/','+','-');
$randoperator = $operator[rand(0,3)];
if($operator = "/" && $rand2 == 0)
echo "Division by zero!";
else {
$finaalvalue = calculate_string($rand1 . $randoperator . $rand2);
echo $rand1.$randoperator.$rand2.'='.$finaalvalue;
}
?>
Suggest you to calculate mathematics operation by switch case. Your system can't perform mathematics operation, it will generate a string. That is concatenation.
$rand1 = rand(0,9);
$rand2 = rand(0,9);
$operator = array('*','/','+','-');
$randoperator = $operator[rand(0,3)];
switch($randoperator){
case '+':
$finaalvalue = $rand1 + $rand2;
break;
case '-':
$finaalvalue = $rand1 - $rand2;
break;
case '/':
if(!$rand2) $rand2++;
$finaalvalue = $rand1 / $rand2;
break;
case '*':
$finaalvalue = $rand1 * $rand2;
break;
}
echo $rand1.$randoperator.$rand2.'='.$finaalvalue;
I have a currency value as follows say,
$6.041 billion USD (2006) or US$6.041 billion (2009)[1] or €6.041 billion (2010)[1].
I want to parse the currency value in such a way that I want to store it in three different variables i.e. $number, $currency, $year (i.e) $number = 6,041,000,000 and$currency = "euro" and $year = 2010.
The problem is that the string might have € or $ or USD. But I need to parse them accordingly.
Also I might end up having million also. According to that succeeding zeros should vary. Also I might or might not have decimal points in the currency. i.e 6.041 billion or 6 billion.
How to handle all the cases and store the result in the three variables I need?
similarly how to handle £(67.1) million (2011)[1] HK $ 648 million (2006) 22,440,000, 1,325.26 crore (US$241.2 million) [4].?
I am thinking of a brute force solution to handle each case one by one.
But that is not a apt one.
Is there any simplest way to do this?
Any help would be appreciated?
You could try running regular expressions something like this (untested):
if(preg_match('/([$€])([\d\.]+)\s?([\w]+)[^\(]*\((\d+)\)/',$value,$matches)){
switch($matches[1]){
case '$':
$currency = 'dollar';
break;
case '€':
$currency = 'euro';
break;
// and more for more currencies
}
$number = $matches[2];
switch($matches[3]){
case 'billion':
$number = intval($number*1000000000);
break;
case 'million':
$number = intval($number*1000000);
break;
// and more for more multipliers
}
$year = $matches[4];
}
Remember to add all the possible currency symbols you need to support in the first pair of square brackets in the regular expression [$€].
Untested and I am sure there are more elegant ways to do things, but this should work:
<?php
echo parseCurrency('$6.041 billion USD (2006)');
function parseCurrency($input){
if(strpos($input, 'USD') || strpos($input, '$')){
$currency = 'USD';
$floatVal = (float) get_string($input, '$', ' ');
}
elseif(strpos($input, '€')){
$currency = 'EUR';
$floatVal = (float) get_string($input, '€', ' ');
}
else{
$currency = 'undefined';
die();
}
if(strpos($input, 'billion'){
$number = $floatVal * 1000000000;
}
elseif(strpos($input, 'million'){
$number = $floatVal * 1000000;
}
else{
$number = 'undefined';
die();
}
if (preg_match('/\\([12][0-9]{3}\\)/', $input, $years)){
$year = $years[0];
}
else{
$year = 'undefined';
die();
}
return $number . ', ' . $currency . ', ' . $year;
}
//used to find million or billion
function get_string($string, $start, $end){
$string = " ".$string;
$pos = strpos($string,$start);
if ($pos == 0) return "";
$pos += strlen($start);
$len = strpos($string,$end,$pos) - $pos;
return substr($string,$pos,$len);
}
is there any way to edit/change the default locale setting in localeconv()?
I would like to use the the money_format function, and it works fine, but the locales for my language/region are not correct.
To be more precise, for Croatia, we use the currency symbol after the number, not before like set in local values?
Are there any ways I can edit this? Or at least manually check, change values, and send new values to setlocale()?
Working on shared hosting btw.
number_format() has nothing to do with currency symbols, you probably meant money_format(), but ... well - just use number_format() and append whatever currency symbol you want to the return value.
If anyone is interested, I made it work with my own replacement of the money_format() function.
It is basically copy-paste from here with added parameters for forceRight and noSpace
class Helper_Locales
{
public static function formatNumber($number, $isMoney=false, $forceRight=false, $noSpace=false) {
$lg = isset($lg) ? $lg : setlocale(LC_MONETARY, '0');
$ret = setLocale(LC_ALL, $lg);
setLocale(LC_TIME, 'Europe/Paris');
if ($ret===FALSE) {
echo "Language '$lg' is not supported by this system.\n";
return;
}
$LocaleConfig = localeConv();
forEach($LocaleConfig as $key => $val) $$key = $val;
// Sign specifications:
if ($number>=0) {
$sign = $positive_sign;
$sign_posn = $p_sign_posn;
$sep_by_space = $p_sep_by_space;
$cs_precedes = $p_cs_precedes;
} else {
$sign = $negative_sign;
$sign_posn = $n_sign_posn;
$sep_by_space = $n_sep_by_space;
$cs_precedes = $n_cs_precedes;
}
// Number format:
$n = number_format(abs($number), $frac_digits,
$decimal_point, $thousands_sep);
$n = str_replace(' ', ' ', $n);
switch($sign_posn) {
case 0: $n = "($n)"; break;
case 1: $n = "$sign$n"; break;
case 2: $n = "$n$sign"; break;
case 3: $n = "$sign$n"; break;
case 4: $n = "$n$sign"; break;
default: $n = "$n [error sign_posn=$sign_posn !]";
}
// Currency format:
$currency_symbol = strtolower($currency_symbol);
$m = number_format(abs($number), $frac_digits,
$mon_decimal_point, $mon_thousands_sep);
if ($sep_by_space && !$noSpace) $space = ' '; else $space = '';
if ($cs_precedes && !$forceRight) $m = "$currency_symbol$space$m";
else $m = "$m$space$currency_symbol";
$m = str_replace(' ', ' ', $m);
switch($sign_posn) {
case 0: $m = "($m)"; break;
case 1: $m = "$sign$m"; break;
case 2: $m = "$m$sign"; break;
case 3: $m = "$sign$m"; break;
case 4: $m = "$m$sign"; break;
default: $m = "$m [error sign_posn=$sign_posn !]";
}
if ($isMoney) return $m; else return $n;
}
}