【发布时间】:2018-07-11 01:59:44
【问题描述】:
编辑:
我不知道这是否可以在正则表达式中重新创建,@Paul Crovella 指出这可能不适合解决问题,但只是为了好玩,我想做这样的事情:
- 从右到左开始。匹配点或逗号的第一个字符
/(?<seperator>[.,])\d+$/ - 重置指针并递归捕获每个数字直到十进制字符(不捕获除数字以外的任何内容)
/(?<number>(?:\d+[^\1])+\d+)/ - 获取小数位
/(?<decimal)\d+(?<=\1)/
附加规则
- 如果只有一个 [.,] 则为小数点
- 如果只有其中一个 [.,\h] 则为百/千分隔符
- 如果多次找到第一个捕获的非数字字符,则为百/千分隔符
- 百/千总是相同的,所以应该可以编写一个递归的前瞻,它总是在字符处停止并用数字“填充”一个组
原文:
我正在用 PHP 构建一个在单位之间转换的类。到目前为止,我已经完成了所有工作,现在我正在尝试创建一种强大的方法来将输入字符串转换为浮点数。
这是我的班级应该处理的一些测试字符串:
123456789
1234567.89
1234567,89
1,234,567.89
1.234.567,89
123 456 789
1 234 567.89
1 234 567,89
为了使这个可行,我必须做出一些假设:
- 字符串可以是整数
- 字符串可以包含由
[.,]分隔的小数位 - 字符串可以分组(按数百/千),以
[.,\h]分隔 - 分隔符是一致的,但彼此不同
我认为最好的“做一次,做对”的方法是用正则表达式来解决这个问题。
首先你必须收集第一个分隔符
/^\d+(?<s>[.,\h])/
然后你必须重置指针并反向引用符号
/^(?<b>(\d+)${s}(\d+))/
我不想在实际组中使用分隔符,但我不知道如何实现。
下一步是为小数组匹配[^${s}](?<d>\d+)。
最后将两个数相加
return (float) $matches['b'] . '.' . $matches['d'];
我想出了一些解决方案,但没有一个是完全正确的。我希望社区提供一些意见。请描述每个区块的作用,以便我向您学习。
最好的问候。
附:添加解析这些的可能性的奖励积分
123^2
123^-2
123 ^2
123^ 2
123²
123³
前四个我可以做到,但对于后两个,我正在寻找一种将上标替换为数字的方法(我也可以使用 str_replace 做到这一点,但我知道这在正则表达式本身中应该是可能的)。
【问题讨论】:
-
那么你想如何解决像
123,456这样的模糊字符串,可以解释为123456.0或123.456?还是所有输入字符串的小数点都不超过 2 位? -
假设小数始终是小数点后 2 位,我认为这可行。 3v4l.org/nclkR
-
php.net/manual/en/numberformatter.parse.php是这个问题比较合适的解决方案
-
这是个好问题!我认为最安全的选择是,不传递额外的函数参数,只是假设如果只有一个点或逗号,它应该是小数点。
-
加入假设和模棱两可是“稳健”解决方案的反面。