I’ve been hacking somebody else’s CMS (without access to the main engine) and needed to calculate a mathematical function on some prices. Specifically needed to display a percentage drop when given an original price as well as the current price. Here follows the journey. [Jump to The Solution.]

Easy right?

if($originalPrice > 0) {
    $percentageDrop = intval(100*(($originalPrice - $currentPrice)/$originalPrice));

There was a Problem. The prices are stored not as integers but as formatted currency; ie “€ 120,000”

OK – easy – I found a simple solution to strip non alphanumerics (and space) and adapted it slightly:

function numericFromString( $string )
    return preg_replace('/[^0-9]/', '', $string);

This function is then applied like so:
$currentPrice = numericFromString( ' € 120,000 ' ) ;

Worked in principle but not in practice – numbers seemed to balloon in size. [I didn’t spot it all the numbers which had ‘8364’ at the beginning…]

I had to call in Dave “tech support” Watson. “Bingo!” he said.

The problem [you’ve figured it out already… ] is that the euro symbol is a numeric HTML entity: &#8364;. There’s a bunch of numbers in there too. In fact – 8364.


So Dave took my adapted [and useless] function and made it work. Now it looks like this:

The Solution

function numericFromString($string) {
    $string = str_replace('&#8364;','',$string);
    return preg_replace('/[^0-9]/','', html_entity_decode($string));

Why the extra line with str_replace? Because html_entity_decode doesn’t actually decode numerical html entities…

Would you believe it?

For more bullet proof results it may be worthwhile to try the following in place of that str_replace (from the comments at the official PHP manual at php.net)

$string = preg_replace('/&#(d+);/me',"chr(\1)",$string); //decimal notation
$string = preg_replace('/&#x([a-f0-9]+);/mei',"chr(0x\1)",$string);  //hex notation