Parse formatted Money String into Number [duplicate] - php

Is there a way to get the float value of a string like this: 75,25 €, other than parsefloat(str_replace(',', '.', $var))?
I want this to be dependent on the current site language, and sometimes the comma could be replaced by dot.

This is a bit more complex/ slow solution, but works with all locales. #rlenom's solution work only with dots as decimal separator, and some locales, like Spanish, use the comma as decimal separator.
<?php
public function getAmount($money)
{
$cleanString = preg_replace('/([^0-9\.,])/i', '', $money);
$onlyNumbersString = preg_replace('/([^0-9])/i', '', $money);
$separatorsCountToBeErased = strlen($cleanString) - strlen($onlyNumbersString) - 1;
$stringWithCommaOrDot = preg_replace('/([,\.])/', '', $cleanString, $separatorsCountToBeErased);
$removedThousandSeparator = preg_replace('/(\.|,)(?=[0-9]{3,}$)/', '', $stringWithCommaOrDot);
return (float) str_replace(',', '.', $removedThousandSeparator);
}
Tests:
['1,10 USD', 1.10],
['1 000 000.00', 1000000.0],
['$1 000 000.21', 1000000.21],
['£1.10', 1.10],
['$123 456 789', 123456789.0],
['$123,456,789.12', 123456789.12],
['$123 456 789,12', 123456789.12],
['1.10', 1.1],
[',,,,.10', .1],
['1.000', 1000.0],
['1,000', 1000.0]
Caveats:
Fails if the decimal part have more than two digits.
This is an implementation from this library:
https://github.com/mcuadros/currency-detector

use ereg_replace
$string = "$100,000";
$int = ereg_replace("[^0-9]", "", $string);
echo $int;
outputs
1000000
function toInt($str)
{
return (int)preg_replace("/\..+$/i", "", preg_replace("/[^0-9\.]/i", "", $str));
}
Update
<?php
$string = array("$1,000,000.00","$1 000 000.00","1,000 000.00","$123","$123 456 789","0.15¢");
foreach($string as $s) {
echo $s . " = " . toInt($s) . "\n";
}
function toInt($str)
{
return preg_replace("/([^0-9\\.])/i", "", $str);
}
?>
Outputs
$1,000,000.00 = 1000000.00
$1 000 000.00 = 1000000.00
1,000 000.00 = 1000000.00
$123 = 123
$123 456 789 = 123456789
0.15¢ = 0.15
and if you cast it as an integer
<?php
$string = array("$1,000,000.00","$1 000 000.00","1,000 000.00","$123","$123 456 789","0.15¢");
foreach($string as $s) {
echo $s . " = " . _toInt($s) . "\n";
}
function _toInt($str)
{
return (int)preg_replace("/([^0-9\\.])/i", "", $str);
}
?>
outputs
$1,000,000.00 = 1000000
$1 000 000.00 = 1000000
1,000 000.00 = 1000000
$123 = 123
$123 456 789 = 123456789
0.15¢ = 0
So there you have it. single line, one replace. you're good to go.

You can use
NumberFormatter::parseCurrency - Parse a currency number
Example from Manual:
$formatter = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
var_dump($formatter->parseCurrency("75,25 €", $curr));
gives: float(75.25)
Note that the intl extension is not enabled by default. Please refer to the Installation Instructions.

You're gonna need to remove the currency symbol from the string. PHP's intval stops at the 1st non-numeric character it finds.
$int = intval(preg_replace('/[^\d\.]/', '', '$100')); // 100
Though if you have a value like $100.25, you might wanna use floatval instead.
$float = floatval(preg_replace('/[^\d\.]/', '', '$100.25')); // 100.25

PHP has intval (here are the docs), which is (as far as I can tell) exactly the same as JavaScript's parseInt.
However, for what's worth, I don't think either function will help you with what you're trying to do. Because the first character is non-numeric, both freak out (PHP will give you 0, JS will give you NaN). So in either language, you're going to have to do some string/regex parsing.

I'm an newbie, so there's probably an obvious (to others, not me) downside to the approach below, but thought I would share it anyway. I'd be interested to know whether it's faster or slower than using preg_replace, but didn't do any speed testing.
$badChars = array("$", ",", "(", ")");
$dirtyString = "($3,895.23)";
$cleanString = str_ireplace($badChars, "", $dirtyString);
echo "$dirtyString becomes $cleanString<p>";
$dirtyString can be an array, so:
$badChars = array("$", ",", "(", ")");
$dirtyStrings = array("($3,895.23)", "1,067.04", "$5683.22", "$9834.48");
$cleanStrings = str_ireplace($badChars, "", $dirtyStrings);
echo var_dump($cleanStrings);

Casting is your friend:
$int = (int) $string;
Update based on op:
Try something like this:
<?php
function extract_numbers($string)
{
return preg_replace("/[^0-9]/", '', $string);
}
echo extract_numbers('$100');
?>
Demo: http://codepad.org/QyrfS7WE

I had a similar problem where I didn't receive the currency symbol, just the strings (ie: 1,234,567.89 or 1.234.567,89).
This helped me normalize both cases into floats:
$val = str_replace(",", ".", $formatted);
$val = preg_replace("/[\,\.](\d{3})/", "$1", $val);
But Gordon's answer is much cleaner.

Related

Using PHP preg_replace match result in a math operation?

I want to find a number in a string, add one to it, and replace it. These don't work:
$new_version =
preg_replace("/str\/(\d+)str/", "str/".("$1"+1)."str", $original);
$new_version =
preg_replace("/str\/(\d+)str/", "str/".(intval("$1")+1)."str", $original);
Where 'str' is a very identifiable string, each side of the number (and does not contain numbers).
I realise I can do this in more than one line of code quite easily but it seems like this should be possible.
Using a callback function allows you to cast a match to number and increment, e.g.:
preg_replace_callback(
"/str\/(\d+)str/",
function($matches) { return "str/" . ((int)$matches[1] + 1) . "str"; },
$original
);
Solely using str_replace you can get the number from the string, add one to it, and the replace the old number with the new one :
$str = 'In My Cart : 11 items';
$nb = preg_replace('/\D/', '', $str);
$nb += 1;
$str = str_replace($nb-1, $nb, $str);
echo $str;

I want to change format of height 5'4" to 5.4, so how can i replace this format with str_replace?

I want to change format of height 5'4" to 5.4, so how can i replace this format with str_replace
$str = str_replace("'", '.', $model->hight);
print_r($str);
This is my code it returns 5'6" => 5.6" but i want to replace " to " "(blank) also like 5.6
$str = rtrim(str_replace("'",'.',$model->hight), '"');
Since we were discussing that there are 12 inches in a foot, and 5'6" is actually 5.5 feet, then you could use something more elaborate to calculate the decimal value of feet, such as this:
<?php
$str = '5\'6"';
// Get rid of the double quote on the right
$str = rtrim( $str, '"' );
// Feet will be $parts[0], and inches will be $parts[1]
$parts = explode( "'", $str );
$inches = $parts[0] * 12;
if( isset( $parts[1] ) )
$inches += $parts[1];
$decimal = $inches / 12;
echo $decimal;
Keep in mind though, this calculation does not take into account if there are fractions of an inch.
str_replace('"','',str_replace("'",'.',$model->hight));

Parse a number but keep negative's

I am trying to un-format a number to it's original form but keep whether or not it is negative. Someone on stack overflow led me to this code that work's very nicely but it does not keep the negative.
Could anyone help me get a better fix on this?
EDIT - For USD Currency/normal numbers
Example:
1,234 = 1234
-1,234 = -1234
1,234.00 = 1234
1,234.56 = 1234.56
function numberUnformat($number)
{
$cleanString = preg_replace('/([^0-9\.,])/i', '', $number);
$onlyNumbersString = preg_replace('/([^0-9])/i', '', $number);
$separatorsCountToBeErased = strlen($cleanString) - strlen($onlyNumbersString) - 1;
$stringWithCommaOrDot = preg_replace('/([,\.])/', '', $cleanString, $separatorsCountToBeErased);
$removedThousendSeparator = preg_replace('/(\.|,)(?=[0-9]{3,}$)/', '', $stringWithCommaOrDot);
return (float) str_replace(',', '.', $removedThousendSeparator);
}
In case you have the ICU extension (which is bundled in PHP 5.3) available, try this:
$formatter = new NumberFormatter('en_US', NumberFormatter::DECIMAL);
echo $formatter->parse('-1,234.56');
Change your regular expression to match the negative numbers, too:
$cleanString = preg_replace('/([^\-0-9\.,])/i', '', $number);
Test cases:
echo numberUnformat('1,234')."\n";
echo numberUnformat('-1,234')."\n";
echo numberUnformat('1,234.00')."\n";
echo numberUnformat('1,234.56 ')."\n";
Output:
1234
-1234
1234
1234.56
Demo!
If you want to remove any extraneous minus signs in the middle of the string, too:
$cleanString = preg_replace('/[^0-9.,-]|(?<=.)-/', '', $number);
$onlyNumbersString = preg_replace('/[^0-9-]|(?<=.)-/', '', $number);
Note that you don't need the parentheses, backslash, or /i in your original.
I would actually add some parameters to the function to allow specification of grouping and decimal separators (and possibly allow ability to cast to float or decimal and go to a solution like this:
function number_unformat($num_string, $group_sep = ',', $dec_sep = '.', $cast_to_type = true) {
if (substr_count($num_string, $dec_sep) > 1) {
// input was invalid
throw new Exception('Inavlid string: `' . $num_string . '` passed to function. Too many decimal separators.');
}
// remove grouping separator
$string = str_replace($group_sep, '', $num_string);
if (true === $cast_to_type) {
// change any decimal separators to periods before casting
$string = str_replace($dec_sep, '.', $string, $count);
if ($count === 1) {
return (float)$string;
} else {
return (int)$string;
}
} else {
return $string;
}
}
Note that there is no need at all to use regular expression here.
A fairly quick (though imperfect) fix would be to change the first two lines of the function:
$cleanString = preg_replace('/([^-0-9\.,])/i', '', $number);
$onlyNumbersString = preg_replace('/([^-0-9])/i', '', $number);
Though this will cause a problem if you have a number like 2-434.43.
One could muck with the regular expressions to keep the negative, but to me it's simpler to do the following at the end:
$absvalue = (float) str_replace(',', '.', $removedThousendSeparator);
if ($number[0] == '-') {
$absvalue = $absvalue * -1.0;
}
return $absvalue;
I might have a syntax error in there, my PHP is rusty, but the idea is just to check and see if the input string starts with a negative sign, and if it does, multiply the result by negative 1.

How to convert a string with numbers and spaces into an int

I have a small problem. I am tryng to convert a string like "1 234" to a number:1234
I cant't get there. The string is scraped fro a website. It is possible not to be a space there? Because I've tried methods like str_replace and preg_split for space and nothing. Also (int)$abc takes only the first digit(1).
If anyone has an ideea, I'd be greatefull! Thank you!
This is how I would handle it...
<?php
$string = "Here! is some text, and numbers 12 345, and symbols !£$%^&";
$new_string = preg_replace("/[^0-9]/", "", $string);
echo $new_string // Returns 12345
?>
intval(preg_replace('/[^0-9]/', '', $input))
Scraping websites always requires specific code, you know how you receive the input - and you write code that is required to make it usable.
That is why first answer is still str_replace.
$iInt = (int)str_replace(array(" ", ".", ","), "", $iInt);
$str = "1 234";
$int = intval(str_replace(' ', '', $str)); //1234
I've just came into the same issue, however the answer that was provided wasn't covering all the different cases I had...
So I made this function (the idea popped in my mind thanks to Dan) :
function customCastStringToNumber($stringContainingNumbers, $decimalSeparator = ".", $thousandsSeparator = " "){
$numericValues = $matches = $result = array();
$regExp = null;
$decimalSeparator = preg_quote($decimalSeparator);
$regExp = "/[^0-9$decimalSeparator]/";
preg_match_all("/[0-9]([0-9$thousandsSeparator]*)[0-9]($decimalSeparator)?([0-9]*)/", $stringContainingNumbers, $matches);
if(!empty($matches))
$matches = $matches[0];
foreach($matches as $match):
$numericValues[] = (float)str_replace(",", ".", preg_replace($regExp, "", $match));
endforeach;
$result = $numericValues;
if(count($numericValues) === 1)
$result = $numericValues[0];
return $result;
}
So, basically, this function extracts all the numbers contained inside of a string, no matter how many text there is, identifies the decimal separator and returns every extracted number as a float.
One can specify what decimal separator is used in one's country with the $decimalSeparator parameter.
Use this code for removing any other characters like .,:"'\/, !##$%^&*(), a-z, A-Z :
$string = "This string involves numbers like 12 3435 and 12.356 and other symbols like !## then the output will be just an integer number!";
$output = intval(preg_replace('/[^0-9]/', '', $string));
var_dump($output);

Unformat money when parsing in PHP

Is there a way to get the float value of a string like this: 75,25 €, other than parsefloat(str_replace(',', '.', $var))?
I want this to be dependent on the current site language, and sometimes the comma could be replaced by dot.
This is a bit more complex/ slow solution, but works with all locales. #rlenom's solution work only with dots as decimal separator, and some locales, like Spanish, use the comma as decimal separator.
<?php
public function getAmount($money)
{
$cleanString = preg_replace('/([^0-9\.,])/i', '', $money);
$onlyNumbersString = preg_replace('/([^0-9])/i', '', $money);
$separatorsCountToBeErased = strlen($cleanString) - strlen($onlyNumbersString) - 1;
$stringWithCommaOrDot = preg_replace('/([,\.])/', '', $cleanString, $separatorsCountToBeErased);
$removedThousandSeparator = preg_replace('/(\.|,)(?=[0-9]{3,}$)/', '', $stringWithCommaOrDot);
return (float) str_replace(',', '.', $removedThousandSeparator);
}
Tests:
['1,10 USD', 1.10],
['1 000 000.00', 1000000.0],
['$1 000 000.21', 1000000.21],
['£1.10', 1.10],
['$123 456 789', 123456789.0],
['$123,456,789.12', 123456789.12],
['$123 456 789,12', 123456789.12],
['1.10', 1.1],
[',,,,.10', .1],
['1.000', 1000.0],
['1,000', 1000.0]
Caveats:
Fails if the decimal part have more than two digits.
This is an implementation from this library:
https://github.com/mcuadros/currency-detector
use ereg_replace
$string = "$100,000";
$int = ereg_replace("[^0-9]", "", $string);
echo $int;
outputs
1000000
function toInt($str)
{
return (int)preg_replace("/\..+$/i", "", preg_replace("/[^0-9\.]/i", "", $str));
}
Update
<?php
$string = array("$1,000,000.00","$1 000 000.00","1,000 000.00","$123","$123 456 789","0.15¢");
foreach($string as $s) {
echo $s . " = " . toInt($s) . "\n";
}
function toInt($str)
{
return preg_replace("/([^0-9\\.])/i", "", $str);
}
?>
Outputs
$1,000,000.00 = 1000000.00
$1 000 000.00 = 1000000.00
1,000 000.00 = 1000000.00
$123 = 123
$123 456 789 = 123456789
0.15¢ = 0.15
and if you cast it as an integer
<?php
$string = array("$1,000,000.00","$1 000 000.00","1,000 000.00","$123","$123 456 789","0.15¢");
foreach($string as $s) {
echo $s . " = " . _toInt($s) . "\n";
}
function _toInt($str)
{
return (int)preg_replace("/([^0-9\\.])/i", "", $str);
}
?>
outputs
$1,000,000.00 = 1000000
$1 000 000.00 = 1000000
1,000 000.00 = 1000000
$123 = 123
$123 456 789 = 123456789
0.15¢ = 0
So there you have it. single line, one replace. you're good to go.
You can use
NumberFormatter::parseCurrency - Parse a currency number
Example from Manual:
$formatter = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
var_dump($formatter->parseCurrency("75,25 €", $curr));
gives: float(75.25)
Note that the intl extension is not enabled by default. Please refer to the Installation Instructions.
You're gonna need to remove the currency symbol from the string. PHP's intval stops at the 1st non-numeric character it finds.
$int = intval(preg_replace('/[^\d\.]/', '', '$100')); // 100
Though if you have a value like $100.25, you might wanna use floatval instead.
$float = floatval(preg_replace('/[^\d\.]/', '', '$100.25')); // 100.25
PHP has intval (here are the docs), which is (as far as I can tell) exactly the same as JavaScript's parseInt.
However, for what's worth, I don't think either function will help you with what you're trying to do. Because the first character is non-numeric, both freak out (PHP will give you 0, JS will give you NaN). So in either language, you're going to have to do some string/regex parsing.
I'm an newbie, so there's probably an obvious (to others, not me) downside to the approach below, but thought I would share it anyway. I'd be interested to know whether it's faster or slower than using preg_replace, but didn't do any speed testing.
$badChars = array("$", ",", "(", ")");
$dirtyString = "($3,895.23)";
$cleanString = str_ireplace($badChars, "", $dirtyString);
echo "$dirtyString becomes $cleanString<p>";
$dirtyString can be an array, so:
$badChars = array("$", ",", "(", ")");
$dirtyStrings = array("($3,895.23)", "1,067.04", "$5683.22", "$9834.48");
$cleanStrings = str_ireplace($badChars, "", $dirtyStrings);
echo var_dump($cleanStrings);
Casting is your friend:
$int = (int) $string;
Update based on op:
Try something like this:
<?php
function extract_numbers($string)
{
return preg_replace("/[^0-9]/", '', $string);
}
echo extract_numbers('$100');
?>
Demo: http://codepad.org/QyrfS7WE
I had a similar problem where I didn't receive the currency symbol, just the strings (ie: 1,234,567.89 or 1.234.567,89).
This helped me normalize both cases into floats:
$val = str_replace(",", ".", $formatted);
$val = preg_replace("/[\,\.](\d{3})/", "$1", $val);
But Gordon's answer is much cleaner.

Categories