如何在 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 中一起添加货币字符串(非标准化输入)?的主要内容,如果未能解决你的问题,请参考以下文章