【问题标题】:Unformat money when parsing in PHP在 PHP 中解析时取消格式化钱
【发布时间】:2011-07-05 14:49:12
【问题描述】:

除了parsefloat(str_replace(',', '.', $var))之外,有没有办法获得像这样的字符串的浮点值:75,25 €

我希望这取决于当前的网站语言,有时逗号可以替换为点。

【问题讨论】:

标签: php parsing floating-point currency


【解决方案1】:

这是一个更复杂/缓慢的解决方案,但适用于所有语言环境。 @rlenom 的解决方案仅使用点作为小数分隔符,并且某些语言环境(如西班牙语)使用逗号作为小数分隔符。

<?php

public function getAmount($money)
{
    $cleanString = preg_replace('/([^0-9\.,])/i', '', $money);
    $onlyNumbersString = preg_replace('/([^0-9])/i', '', $money);

    $separatorsCountToBeErased = strlen($cleanString) - strlen($onlyNumbersString) - 1;

    $stringWithCommaOrDot = preg_replace('/([,\.])/', '', $cleanString, $separatorsCountToBeErased);
    $removedThousandSeparator = preg_replace('/(\.|,)(?=[0-9]{3,}$)/', '',  $stringWithCommaOrDot);

    return (float) str_replace(',', '.', $removedThousandSeparator);
}

测试:

['1,10 USD', 1.10],
['1 000 000.00', 1000000.0],
['$1 000 000.21', 1000000.21],
['£1.10', 1.10],
['$123 456 789', 123456789.0],
['$123,456,789.12', 123456789.12],
['$123 456 789,12', 123456789.12],
['1.10', 1.1],
[',,,,.10', .1],
['1.000', 1000.0],
['1,000', 1000.0]

注意事项: 如果小数部分超过两位数,则失败。

这是来自这个库的一个实现: https://github.com/mcuadros/currency-detector

【讨论】:

  • 出色的解决方案,谢谢。测试用例表示赞赏
  • 仅供参考:从stackoverflow.com/questions/7407946/…合并到这里
  • +1 对于这个解决方案,即使是法裔加拿大数字也适用于我: $fr_num = "180,000,08 $";返回:双(180000.08)
  • 字符类中的点不需要转义。
  • 我必须检查字符串是否以“-”开头,在这种情况下将结果乘以 -1 以更改其符号,否则这会将所有负数转换为正数。
【解决方案2】:

使用 ereg_replace

$string = "$100,000";
$int = ereg_replace("[^0-9]", "", $string); 
echo $int;

输出

1000000

function toInt($str)
{
    return (int)preg_replace("/\..+$/i", "", preg_replace("/[^0-9\.]/i", "", $str));
}

更新


<?php
$string = array("$1,000,000.00","$1 000 000.00","1,000 000.00","$123","$123 456 789","0.15¢");
foreach($string as $s) {
    echo $s . " = " . toInt($s) . "\n"; 
}
function toInt($str)
{
    return preg_replace("/([^0-9\\.])/i", "", $str);
}
?>

输出

$1,000,000.00 = 1000000.00
$1 000 000.00 = 1000000.00
1,000 000.00 = 1000000.00
$123 = 123
$123 456 789 = 123456789
0.15¢ = 0.15

如果你把它转换成整数

<?php
$string = array("$1,000,000.00","$1 000 000.00","1,000 000.00","$123","$123 456 789","0.15¢");
foreach($string as $s) {
    echo $s . " = " . _toInt($s) . "\n";    
}
function _toInt($str)
{
    return (int)preg_replace("/([^0-9\\.])/i", "", $str);
}
?>

输出

$1,000,000.00 = 1000000
$1 000 000.00 = 1000000
1,000 000.00 = 1000000
$123 = 123
$123 456 789 = 123456789
0.15¢ = 0

所以你有它。单行,一个替换。你可以走了。

【讨论】:

  • 非常感谢。我希望我可以不使用正则表达式而侥幸,但这不是一项对性能至关重要的任务,所以这很好。另外,ereg_replace() is deprecated - 改用preg_replace() :-)
  • 可能想将. 添加到正则表达式中,否则$100.00 将等于10000
  • 对不起,5.2天我太习惯了。
  • 主要作为参考,我有this function。有没有办法把它缩小成一行?
  • @JamWaffles,是的……就是这样。
【解决方案3】:

你可以使用

手册示例:

$formatter = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
var_dump($formatter->parseCurrency("75,25 €", $curr));

给:float(75.25)

请注意,intl extension 默认情况下未启用。请参考Installation Instructions

【讨论】:

  • +1 这是一个很好的方法,但仅限 PHP 5.3。这可能是一个巨大的限制
  • @Ben PHP5.2 已终止支持。此外,intl 扩展在 PHP 5.3 之前的 PECL 中可用,因此版本不是问题。
  • @VladislavRastrusny 它在手册中所说的内容:“接收货币名称的参数(3 个字母的 ISO 4217 货币代码)。”这里重要的词是接收。它是通过引用传递的。想想preg_match 中的 $matches。
  • 在您的示例中$curr 是什么?
  • @Adam 表示货币的字符串;比如美元或欧元。
【解决方案4】:

您需要从字符串中删除货币符号。 PHP 的intval 停在它找到的第一个非数字字符处。

$int = intval(preg_replace('/[^\d\.]/', '', '$100')); // 100

虽然如果您有 $100.25 这样的值,您可能想改用 floatval

$float = floatval(preg_replace('/[^\d\.]/', '', '$100.25')); // 100.25

【讨论】:

【解决方案5】:

PHP 有 intval (here are the docs),它(据我所知)与 JavaScript 的 parseInt 完全相同。

但是,就其价值而言,我认为这两种功能都无法帮助您完成您想做的事情。因为第一个字符不是数字,所以都吓坏了(PHP 会给你 0,JS 会给你NaN)。所以在任何一种语言中,你都必须做一些字符串/正则表达式解析。

【讨论】:

【解决方案6】:

我是新手,所以下面的方法可能有一个明显的(对其他人,而不是我)缺点,但我想无论如何我都会分享它。我很想知道它是否比使用 preg_replace 更快或更慢,但没有进行任何速度测试。

$badChars = array("$", ",", "(", ")");
$dirtyString = "($3,895.23)";
$cleanString = str_ireplace($badChars, "", $dirtyString);
echo "$dirtyString becomes $cleanString<p>";

$dirtyString 可以是一个数组,所以:

$badChars = array("$", ",", "(", ")");
$dirtyStrings = array("($3,895.23)", "1,067.04", "$5683.22", "$9834.48");
$cleanStrings = str_ireplace($badChars, "", $dirtyStrings);

echo var_dump($cleanStrings);

【讨论】:

  • 仅供参考:从stackoverflow.com/questions/7407946/…合并到这里
  • 像其他一些建议一样,这仅限于使用“。”的语言环境。作为小数和“,”作为千位分隔符。对于那些使用逗号作为小数分隔符的人来说,“,”不是一个坏字符。
【解决方案7】:

选角是你的朋友:

$int = (int) $string;

更新 基于op

试试这样的:

<?php

function extract_numbers($string)
{
    return preg_replace("/[^0-9]/", '', $string);
}

echo extract_numbers('$100');

?>

演示:http://codepad.org/QyrfS7WE

【讨论】:

  • 当字符串包含其他非数字字符(如 OP 的示例)时,这会起作用吗?
  • @Rocket -- 嗯,我现在明白了……调查一下
  • 我在发布我的问题之前对此进行了试验,但没有奏效 - 我得到的结果与 @Rocket 相同。
  • 谢谢尼尔。您的答案与@rlemon 的相同,因此两者都是正确的。我将 rlemon 的答案标记为正确,因为他的代表次数比你少,但我仍然感谢你的努力。
  • 可能想将. 添加到正则表达式中,否则$100.00 将等于10000
【解决方案8】:

我有一个类似的问题,我没有收到货币符号,只有字符串(即:1,234,567.89 或 1.234.567,89)。

这帮助我将这两种情况标准化为浮点数:

$val = str_replace(",", ".", $formatted);
$val = preg_replace("/[\,\.](\d{3})/", "$1", $val);

但 Gordon 的回答要干净得多。

【讨论】:

  • 我在这里留下了更具体的内容:stackoverflow.com/a/13112263/367456 - 但是它不处理数字本身周围的任何货币符号。
  • 然后添加这个过滤掉所有非数字和非分隔符:preg_replace ('/[^\d\,\.]/', '', $val);跨度>
猜你喜欢
  • 1970-01-01
  • 2021-04-13
  • 1970-01-01
  • 2023-03-27
  • 2021-12-30
  • 1970-01-01
  • 2011-08-20
  • 1970-01-01
相关资源
最近更新 更多