Reputation: 9369
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);
}
Upvotes: 5
Views: 3483
Reputation: 71384
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.
Upvotes: 2
Reputation: 2747
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');
Upvotes: 6
Reputation: 95242
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.
Upvotes: 2
Reputation:
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
Upvotes: 2
Reputation: 1188
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.
Upvotes: 0
Reputation: 12577
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.
Upvotes: 0