简体   繁体   中英

Converting a number with comma as decimal point to float

I have a list of prices with a comma for a decimal point and a dot as the thousand separator.

Some examples:

12,30
116,10
1.563,14

These come in this format from a third party. I want to convert them to floats and add them together.

What is the best way to do this? number_format doesn't seem to work with this format, and str_replace seems like overkill, as I have to do it more that once on each number.

Is there are better way? Thanks.

Using str_replace() to remove the dots is not overkill.

$string_number = '1.512.523,55';
// NOTE: You don't really have to use floatval() here, it's just to prove that it's a legitimate float value.
$number = floatval(str_replace(',', '.', str_replace('.', '', $string_number)));

// At this point, $number is a "natural" float.
print $number;

This is almost certainly the least CPU-intensive way you can do this, and odds are that even if you use some fancy function to do it, that this is what it does under the hood.

This function is compatible for numbers with dots or commas as decimals

function floatvalue($val){
            $val = str_replace(",",".",$val);
            $val = preg_replace('/\.(?=.*\.)/', '', $val);
            return floatval($val);
}

This works for all kind of inputs (American or european style)

echo floatvalue('1.325.125,54'); // The output is 1325125.54
echo floatvalue('1,325,125.54'); // The output is 1325125.54
echo floatvalue('59,95');        // The output is 59.95
echo floatvalue('12.000,30');    // The output is 12000.30
echo floatvalue('12,000.30');    // The output is 12000.30

If you're using PHP5.3 or above, you can use numfmt_parse to do "a reversed number_format". If you're not, you stuck with replacing the occurrances with preg_replace/str_replace.

您可以使用NumberFormatter及其parse方法

Might look excessive but will convert any given format no mater the locale:

function normalizeDecimal($val, int $precision = 4): string
{
    $input = str_replace(' ', '', $val);
    $number = str_replace(',', '.', $input);
    if (strpos($number, '.')) {
        $groups = explode('.', str_replace(',', '.', $number));
        $lastGroup = array_pop($groups);
        $number = implode('', $groups) . '.' . $lastGroup;
    }
    return bcadd($number, 0, $precision);
}

Output:

.12           -> 0.1200
123           -> 123.0000
123.91        -> 12345678.9100
123 456 78.91 -> 12345678.9100
123,456,78.91 -> 12345678.9100
123.456.78,91 -> 12345678.9100
123 456 78,91 -> 12345678.9100

Assuming they are in a file or array just do the replace as a batch (ie on all at once):

$input = str_replace(array('.', ','), array('', '.'), $input); 

and then process the numbers from there taking full advantage of PHP's loosely typed nature.

from PHP manual:

str_replace — Replace all occurrences of the search string with the replacement string

I would go down that route, and then convert from string to float - floatval

For those who want an example of NumberFormatter :

    $test='2,345.67';

//  OOP Version
    $numberFormatter=new NumberFormatter('en-AU',NumberFormatter::DECIMAL);
    $number=$numberFormatter->parse($test);
    print $number;

//  Procedural Version
    $numberFormatter=numfmt_create('en_AU',NumberFormatter::DECIMAL);
    $number=numfmt_parse($numberFormatter,$test);
    print $number;

Of course your locale may very.

Not sure why anyone would opt for the procedural version.

Note that one major difference between NumberFormat and the str_replace type solutions is that NumberFormatter is sensitive to where you put your thousands and decimal characters; using 1,2345.00 won't work.

您可以使用filter_var

$floatNumber = (float) filter_var($string, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM