41

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.

jww
  • 97,681
  • 90
  • 411
  • 885
cili
  • 1,037
  • 2
  • 19
  • 34
  • Well there will be localisation issues with regex. – Hamish Feb 28 '11 at 09:18
  • you can use the solution attached at http://stackoverflow.com/questions/7407946/parse-formatted-money-string-into-number/19764699#19764699 – mcuadros Nov 04 '13 at 16:37
  • Maybe related: [Converting a number with comma as decimal point to float](https://stackoverflow.com/q/4325363/608639). – jww Dec 10 '18 at 14:09

8 Answers8

56

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

Braders
  • 447
  • 2
  • 11
mcuadros
  • 4,098
  • 3
  • 37
  • 44
47

You can use

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.

Charles Sprayberry
  • 7,741
  • 3
  • 41
  • 50
Gordon
  • 312,688
  • 75
  • 539
  • 559
  • 3
    +1 This is a great way of doing it but PHP 5.3 only. This might be a huge constraint – Ben Feb 28 '11 at 09:19
  • 3
    @Ben PHP5.2 has reached end of support. Also, the intl extension is available in PECL before PHP 5.3, so the version is not an issue. – Gordon Feb 28 '11 at 09:21
  • @VladislavRastrusny what it says in the manual: "Parameter to receive the currency name (3-letter ISO 4217 currency code)." The important word here is receive. It's passed by reference. Think $matches in `preg_match`. – Gordon Jul 28 '15 at 14:12
  • 3
    What is `$curr` in your example? – Adam Sep 12 '16 at 12:15
  • @Adam a string denoting a currency; like USD or EUR. – Gordon Sep 12 '16 at 12:17
  • `NumberFormatter::DECIMAL` if the string is just an amount without currency symbol. – Fr0zenFyr May 26 '21 at 11:12
47

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.

rlemon
  • 17,518
  • 14
  • 92
  • 123
  • 3
    Thanks very much. I was hoping I could get away with not using regex, but it's not a performance-critical task, so this is fine. Also, [ereg_replace() is deprecated](http://php.net/manual/en/function.ereg-replace.php) - use `preg_replace()` instead :-) – Bojangles Sep 13 '11 at 20:29
  • 6
    Might wanna add `.` to the regex to otherwise `$100.00` would equal `10000`. – gen_Eric Sep 13 '11 at 20:30
  • 1
    sorry, I'm too used to the 5.2 days. – rlemon Sep 13 '11 at 20:31
  • Mainly as reference, I've got [this function](http://pastebin.com/iQN3MnN1). Is there a way to shrink it into one line? – Bojangles Sep 13 '11 at 20:58
  • 2
    @JamWaffles, yup.. there it is. – rlemon Sep 13 '11 at 20:59
  • Sorry for the ambiguity; I meant is there a way to get a minor speed increase by shrinking it to one piece of regex, but thank you anyway! – Bojangles Sep 13 '11 at 21:00
  • @JamWaffles, hehe I figured you meant that, I just wanted to give the literal answer. I'll look it over later. Quittin' time! – rlemon Sep 13 '11 at 21:03
  • shouldn't it be `([^0-9\.])` instead of `([^0-9\\.])` ? Otherwise, the `\\` will not match and it will be left in the final string – bruchowski Aug 02 '13 at 16:45
  • @bruchowski http://tehplayground.com/#YLwjbmpFm looks ok to me. I think you might be technically correct - however this is an old answer and I cannot remember my mindset behind the regex. – rlemon Aug 02 '13 at 18:00
  • FYI: merged here from http://stackoverflow.com/questions/7407946/parse-formatted-money-string-into-number – Shog9 Nov 18 '13 at 07:25
  • mcuadros's solution work for more locales, but thanks for your input though – Cedric Nov 14 '15 at 10:31
  • 1
    May want to update your answer as the `Function ereg_replace()` has been deprecated. – levi Dec 22 '16 at 22:10
  • I don't think your function handles negatives. I had to change it to `doubleval(preg_replace("/([^0-9\-\\.])/i", "", $stringVal))`. Does mine look okay, or is there something wrong with my approach? – Ryan Feb 19 '19 at 00:43
  • Why does a pattern with no letters in it need a case-insensitive pattern modifier? – mickmackusa May 09 '23 at 21:47
10

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
gen_Eric
  • 223,194
  • 41
  • 299
  • 337
  • FYI: merged here from http://stackoverflow.com/questions/7407946/parse-formatted-money-string-into-number – Shog9 Nov 18 '13 at 07:25
2

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);
  • FYI: merged here from http://stackoverflow.com/questions/7407946/parse-formatted-money-string-into-number – Shog9 Nov 18 '13 at 07:26
  • Like some other suggestions, this is limited to locales that use "." as the decimal and "," as the thousands separator. For those that use comma as the decimal separator, "," is NOT a bad char. – lawnbowler Apr 27 '15 at 05:18
2

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.

sdleihssirhc
  • 42,000
  • 6
  • 53
  • 67
  • FYI: merged here from http://stackoverflow.com/questions/7407946/parse-formatted-money-string-into-number – Shog9 Nov 18 '13 at 07:25
1

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

gen_Eric
  • 223,194
  • 41
  • 299
  • 337
Naftali
  • 144,921
  • 39
  • 244
  • 303
  • Will that work when the string contains other non-numeric characters like the OP's examples? – Oliver Charlesworth Sep 13 '11 at 20:22
  • @Rocket -- hmmm i see that now... looking into it – Naftali Sep 13 '11 at 20:23
  • I experimented with this before I posted my question, but it didn't work - I get the same result as @Rocket. – Bojangles Sep 13 '11 at 20:24
  • Thanks Neal. Your answer is the same as @rlemon's, so both are correct. I'm marking rlemon's answer as correct as he has less rep than you, but I thank you for your efforts nonetheless. – Bojangles Sep 13 '11 at 20:30
  • 2
    Might wanna add `.` to the regex to otherwise `$100.00` would equal `10000`. – gen_Eric Sep 13 '11 at 20:30
  • @JamWaffles -- that is not really how it works, but ook.... **Especially** since my new update was before that user even posted an answer, but whatever... – Naftali Sep 13 '11 at 20:36
  • I will accept whichever answer I feel a) is correct and b) deserves the reputation the most. As both your answers are very similar, rlemon gets the tick based on the second criterion. – Bojangles Sep 13 '11 at 20:42
  • oook... thats a very odd and inconsistent way to choose an answer. – Naftali Sep 13 '11 at 20:44
  • _In my own opinion_, I don't think it is, but I'll just leave it here. – Bojangles Sep 13 '11 at 20:57
  • just as a note to the original answer provided. after posting my new update it would seem casting is **not** my friend. :) _just had to say it_ – rlemon Sep 13 '11 at 22:32
  • FYI: merged here from http://stackoverflow.com/questions/7407946/parse-formatted-money-string-into-number – Shog9 Nov 18 '13 at 07:25
1

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.

Edson Medina
  • 9,862
  • 3
  • 40
  • 51
  • I've left something more specific here: http://stackoverflow.com/a/13112263/367456 - however it does not handle any currency symbols around the number itself. – hakre Oct 28 '12 at 19:40
  • then just add this to filter out all non-digit and non-separator characters: preg_replace ('/[^\d\,\.]/', '', $val); – Edson Medina Oct 29 '12 at 09:59