将字符串转换为十进制数的PHP代码

3

我正在基于两个值获取数据。一个是产品价格,另一个是产品折扣。我想要计算它们的差值。问题是这些值来自数据库,格式如下:22,50 €。我获取到这个值后,去掉了“€”符号,并将“,”替换为“.”。但是进行减法计算时,结果并不正确。

数据库中分别存储了变量$discount和$price。

 $price2 = trim($price,'€'); 
 $price2 = str_replace(",",".",$price2);
 $price2 = floatval($price2);

 $discount2 = str_replace(array('€'), '',$discount); 
 $discount2 = str_replace(",",".",$discount2);
 $discount2 = floatval($ver_preco2);


 $result = ($price2 - $discount2);

变量$discount没有被转换为浮点数,不知道原因。这个变量有什么问题?

3
$ver_preco2 是从哪里来的? - John Conde
我觉得你可能打错了,正如John Conde所指出的那样。请检查一下你变量的名称。 - Havenard
2
试试更简单的写法,比如 $result = (preg_replace('/[^\d]/', '', $price) - preg_replace('/[^\d]/', '', $discount)) / 100; - Havenard
1
尝试使用 $price2 = (float)str_replace(array('€', ' ', ','), array('', '', '.'), $price2); 来修正你的价格。 - Carlos Goce
1
@Havenard 谢谢您!正如您所说,这个程序运行得很正确 :) - pc_oc
显示剩余8条评论
1个回答

3

由于这个问题已经被浏览了很多次,我编写了一个函数,可能对其他发现这个问题的人有用。以下是包含一些测试值、函数 currencyToDecimal() 以及一些运行并显示测试的代码的脚本。你只需要函数本身。

如果您有其他未通过的测试用例,请告诉我,以便我们可以调整。

<?php

    $testValues = [
        '22,50 €',
        '22 €',
        '22€',
        '$22.50',
        '$22',
        '$0.50¢',
        '$22 000 000.50',
        '22 000 000,50 €',
        '22.000.000,50 €',
    ];

    /**
     * Convert Currency String to Decimal
     * 
     * Attempts to support international currency formats by first converting them
     * to a standardized format PHP can process consistently. 
     * 
     * First, per the SI/ISO 31-0 standard, there are several delimiting options
     * for the integer portion (before the radix) that allow for easier reading. We need
     * to convert this portion to an integer without readability delimiters.
     * 
     * Second, we need to convert the radix (decimal separator) to a "point" or 
     * "period" symbol.
     * 
     * Finally, we strip unwanted characters and convert to float.
     * 
     * @see https://en.wikipedia.org/wiki/Decimal_separator
     * @see https://en.wikipedia.org/wiki/ISO_31-0
     * @see https://docs.oracle.com/cd/E19455-01/806-0169/overview-9/index.html
     */
    function currencyToDecimal($value) {

        // Ensure string does not have leading/trailing spaces
        $value = trim($value);

        /**
         * Standardize readability delimiters
         *****************************************************/

            // Space used as thousands separator between digits
            $value = preg_replace('/(\d)(\s)(\d)/', '$1$3', $value); 

            // Decimal used as delimiter when comma used as radix
            if (stristr($value, '.') && stristr($value, ',')) {
                // Ensure last period is BEFORE first comma
                if (strrpos($value, '.') < strpos($value, ',')) {
                    $value = str_replace('.', '', $value);
                }
            }

            // Comma used as delimiter when decimal used as radix
            if (stristr($value, ',') && stristr($value, '.')) {
                // Ensure last period is BEFORE first comma
                if (strrpos($value, ',') < strpos($value, '.')) {
                    $value = str_replace(',', '', $value);
                }
            }

        /**
         * Standardize radix (decimal separator)
         *****************************************************/

            // Possible radix options
            $radixOptions = [',', ' '];

            // Convert comma radix to "point" or "period"
            $value = str_replace(',', '.', $value);

        /**
         * Strip non-numeric and non-radix characters
         *****************************************************/

            // Remove other symbols like currency characters
            $value = preg_replace('/[^\d\.]/', '', $value);

        /**
         * Convert to float value
         *****************************************************/

            // String to float first before formatting
            $value = floatval($value);

        /**
         * Give final value 
         *****************************************************/

            return $value;

    }

    // Run tests through function
    echo("ORIGINAL => DECIMAL => DATA TYPE\n");
    echo("*********************************************\n");
    foreach ($testValues as $value) {

        // Run function on test value
        $result = currencyToDecimal($value);

        // Determine data type. NOTE: Per docs, "double" will be 
        // returned for a "float" value.
        $type = gettype($result);
        if ($type === "double") {
            $type = "float";
        }

        // Output [Original] => [Decimal] => [Data Type]
        echo("$value => $result => $type\n");
    }

以下是输出结果:

测试输出

ORIGINAL => DECIMAL => DATA TYPE
*********************************************
22,50 € => 22.5 => float
22 € => 22 => float
22€ => 22 => float
$22.50 => 22.5 => float
$22 => 22 => float
$0.50¢ => 0.5 => float
$22 000 000.50 => 22000000.5 => float
22 000 000,50 € => 22000000.5 => float
22.000.000,50 € => 22000000.5 => float

References:
https://en.wikipedia.org/wiki/Decimal_separator
https://en.wikipedia.org/wiki/ISO_31-0
https://docs.oracle.com/cd/E19455-01/806-0169/overview-9/index.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接