如何在 PHP 中一起添加货币字符串(非标准化输入)?

Posted

技术标签:

【中文标题】如何在 PHP 中一起添加货币字符串(非标准化输入)?【英文标题】:How to add currency strings (non-standardized input) together in PHP? 【发布时间】:2010-09-13 03:50:07 【问题描述】:

我有一个表格,人们可以在其中输入美元值。

可能的输入: $999,999,999.99 999,999,999.99 999999999 99,999 99,999 美元

用户可以随意输入美元值。我想将输入读取为双精度值,以便对它们进行总计。

我尝试将字符串类型转换为双精度,但没有奏效。输出时 Total 刚好等于 50:

$string1 = "$50,000";
$string2 = "$50000";
$string3 = "50,000";
$total = (double)$string1 + (double)$string2 + (double)$string3;
echo $total;

【问题讨论】:

Haabda,与其完全重写一个问题,不如打开一个新问题。重写问题会使所有答案显得格格不入,并使该线程在未来对其他人的有用性大大降低。 【参考方案1】:

http://p2p.wrox.com/topic.asp?TOPIC_ID=3099

一步一步来

[edit] 典型...该站点现在似乎已关闭... :(

【讨论】:

我能把它拉起来。现在看一下。 好吧,帖子上的测试代码有效。但是,由于我对这种 RegEx 内容还很陌生,所以我不太确定如何仅提取数字并将它们相加。 我以为你只是想检查它是否有效?如果你想要这个数字,我想你可以使用字符串函数来删除 $ 和 , 字符(参见 Frosty 的答案中的欧洲大陆地区问题),然后将结果解析为浮点数? 啊……你在我最初回答后添加了数字要求;)【参考方案2】:

不是单行,但如果你去掉',你可以这样做:(这是伪代码)

 m/^\$?(\d+)(?:\.(\d\d))?$/
 $value = $1 + $2/100;

这允许 9.99 美元,但不允许 9 美元。或 9.9 美元,并且没有抱怨错放的千位分隔符(错误或功能?)

这里有一个潜在的“地方性”问题,因为您假设成千上万的人使用“,”和美分作为“。”但在欧洲则相反(例如 1.000,99)

【讨论】:

这将是一家美国公司使用的表格。 英格兰在欧洲,和美国一样【参考方案3】:

正则表达式不会将您的字符串转换为数字。我建议您使用正则表达式来验证该字段(确认它符合您允许的格式之一),然后只循环字符串,丢弃所有非数字和非句点字符。如果您不关心验证,则可以跳过第一步。第二步仍将其删除为仅数字和句点。

顺便说一下,在计算货币价值时,您不能安全地使用浮点数。您将失去精度,并且很可能最终得到与输入不完全匹配的总数。

更新:您可以使用以下两个函数来验证您的输入并将其转换为小数点表示。

function validateCurrency($string)

    return preg_match('/^\$?(\d1,3)(,\d3)*(.\d2)?$/', $string) ||
           preg_match('/^\$?\d+(.\d2)?$/', $string);


function makeCurrency($string)

    $newstring = "";

    $array = str_split($string);
    foreach($array as $char)
    
        if (($char >= '0' && $char <= '9') || $char == '.')
        
            $newstring .= $char;
        
    

    return $newstring;

第一个函数将匹配您可以预期的大量货币格式“$99”、“99,999.00”等。它不会匹配“.00”或“99.”,也不会匹配大多数欧式数字( 99.999,00)。在您的原始字符串上使用它来验证它是否是有效的货币字符串。

第二个函数将删除除数字和小数点以外的所有内容。请注意,它本身仍可能返回无效字符串(例如,“”、“....”和“abc”以“”、“....”和“”出现)。验证字符串后使用它来消除多余的逗号,或者如果您想跳过验证,可以单独使用它。

【讨论】:

那我应该用什么来代替浮点数? 您应该使用定点(而不是浮点)。一个简化的解释是,您存储便士的数量而不是美元(有分数)——假设您永远不会处理便士的分数。如果需要,您可以存储百分之几的便士。所以 1.25 美元 == 125 美元。 Haabda,Davr 使用定点的建议可能足以满足您的需求。如果您需要大量的货币,我建议您寻找专门为处理大量货币而设计的货币类(我敢打赌,有人为 php 编写了一个)。【参考方案4】:

我建议不要使用浮点数来存储货币值。如果总和变大,您可能会出现舍入错误。 (好的,如果它变得非常很大。)

最好使用范围足够大的整数变量,并将输入存储为美分,而不是美元。

【讨论】:

【参考方案5】:

我相信你可以用printf来完成这个,它类似于同名的c函数。它的参数可能有点深奥。也可以使用php的number_format函数

【讨论】:

【参考方案6】:

您永远不想将货币价值表示为浮点数!

例如,采用以下(看似简单的)代码:

$x = 1.0;
for ($ii=0; $ii < 10; $ii++) 
  $x = $x - .1;

var_dump($x);

您可能会假设它会产生零值,但事实并非如此。由于$x 是一个浮点数,它实际上最终会比零多一点(1.38777878078E-16),这本身没什么大不了,但这意味着将值与另一个值进行比较不是保证是正确的。例如$x == 0 会产生错误。

【讨论】:

不,这只是永远不要将 == 与浮点值一起使用的原因。【参考方案7】:

假设您获得的是真实货币价值,您可以简单地去除不是数字或小数点的字符:

(pseudocode) 
newnumber = replace(oldnumber, /[^0-9.]/, //)

现在您可以使用类似

的方式进行转换
double(newnumber)

但是,这不会处理诸如“5.6.3”之类的字符串和其他此类非货币字符串。这就提出了一个问题,“您需要处理格式错误的字符串吗?”

【讨论】:

以上是关于如何在 PHP 中一起添加货币字符串(非标准化输入)?的主要内容,如果未能解决你的问题,请参考以下文章

如何在我的数组中添加货币符号?

如何将变量作为标准输入从 PHP 传递到命令行

如何使用 jquery 正确格式化货币?

如何使用 php 从 mysql 数据库中显示非英文字符?

UITextField - 防止用户输入非标准字符(如表情符号)

在php中从mysql数据库中获取货币符号[重复]