在PHP中接受带十进制和千位分隔符的国际数字
对于一个在线计算器,用户可以输入能源量来计算相应的费用,我需要PHP脚本来接受各种用户输入。“200万和四分之一焦耳”的值可输入为: 2000000.25(默认符号) 2000000.25(带千分位器) 2000000,25(逗号作为小数点) 2.000.000,25(逗号作为小数点,带千位分隔符) 2'000'000.25(替代格式) 2 000 000,25(法文符号) 我怎样才能让脚本意识到这些差异 我的第一次尝试是用默认字符替换替换字符,但是句点(.)可以是十进制或千位分隔符。我尝试使用sscanf,但如何确保它正确读取数字在PHP中接受带十进制和千位分隔符的国际数字,php,number-formatting,setlocale,Php,Number Formatting,Setlocale,对于一个在线计算器,用户可以输入能源量来计算相应的费用,我需要PHP脚本来接受各种用户输入。“200万和四分之一焦耳”的值可输入为: 2000000.25(默认符号) 2000000.25(带千分位器) 2000000,25(逗号作为小数点) 2.000.000,25(逗号作为小数点,带千位分隔符) 2'000'000.25(替代格式) 2 000 000,25(法文符号) 我怎样才能让脚本意识到这些差异 我的第一次尝试是用默认字符替换替换字符,但是句点(.)可以是十进制或千位分隔符。我尝试使用
大多数用户只在小数点后提供两位数字,但我有没有办法区分1.234(1点234,句点作为小数点分隔符)和1.234(壹仟贰佰叁拾肆,句点作为小数点分隔符) 没有办法知道
1.234
是什么意思
- 决定小数点分隔符
- 用该分隔符替换最后一个
或、
- 只允许使用一个分隔符
- 将输入限制为数值、
和、
)、逗号(、
)、空格(
)和撇号(“
)作为数千个分隔符。小数点只能是前两个选项之一。这两组分隔符都可以编辑,以允许更多分隔符或将其限制在适当的位置
我实际做的是通过使用两个简单的preg\u match\u all
调用来查找所有数字列和所有分隔符
完整的代码如下所示,应该是自我解释的,因为我在抛出false
时添加了一些注释。我确信,这可以以某种方式简化,但它现在可以工作,过滤许多错误,甚至允许一些奇怪的组合,例如2000 000.25
或2000'000,25
function check_number($number) {
if ((int) substr($number,0,1) == 0) {
return false; // not starting with a digit greater than 0
}
if ((string) substr($number,-1) != "0" && (int) substr($number,-1) == 0) {
return false; // not ending with a digit
}
preg_match_all('/([^0-9]{2,})/', $number, $sep, PREG_PATTERN_ORDER);
if (isset($sep[0][0])) {
return false; // more than one consecutive non-digit character
}
preg_match_all('/([^0-9]{1})/', $number, $sep, PREG_PATTERN_ORDER);
if (count($sep[0]) > 2 && count(array_unique($sep[0])) > 2) {
return false; // more than 2 different separators
}
elseif (count($sep[0]) > 2) {
$last_sep = array_pop($sep[0]);
if (!in_array($last_sep,array(".",","))) {
return false; // separator not allowed as last one
}
$sep_unique = array_unique($sep[0]);
if (count($sep_unique) > 1) {
return false; // not all separators (except last one) are identical
}
elseif (!in_array($sep_unique[0],array("'",".",","," "))) {
return false; // separator not allowed
}
}
return true;
}
function convert_number($number) {
preg_match_all('/([0-9]+)/', $number, $num, PREG_PATTERN_ORDER);
preg_match_all('/([^0-9]{1})/', $number, $sep, PREG_PATTERN_ORDER);
if (count($sep[0]) == 0) {
// no separator, integer
return (int) $num[0][0];
}
elseif (count($sep[0]) == 1) {
// one separator, look for last number column
if (strlen($num[0][1]) == 3) {
if (strlen($num[0][0]) <= 3) {
// treat as thousands seperator
return (int) ($num[0][0] * 1000 + $num[0][1]);
}
elseif (strlen($num[0][0]) > 3) {
// must be decimal point
return (float) ($num[0][0] + $num[0][1] / 1000);
}
}
else {
// must be decimal point
return (float) ($num[0][0] + $num[0][1] / pow(10,strlen($num[0][1])));
}
}
else {
// multiple separators, check first an last
if ($sep[0][0] == end($sep[0])) {
// same character, only thousands separators, check well-formed nums
$value = 0;
foreach($num[0] AS $p => $n) {
if ($p == 0 && strlen($n) > 3) {
return -1; // malformed number, incorrect thousands grouping
}
elseif ($p > 0 && strlen($n) != 3) {
return -1; // malformed number, incorrect thousands grouping
}
$value += $n * pow(10, 3 * (count($num[0]) - 1 - $p));
}
return (int) $value;
}
else {
// mixed characters, thousands separators and decimal point
$decimal_part = array_pop($num[0]);
$value = 0;
foreach($num[0] AS $p => $n) {
if ($p == 0 && strlen($n) > 3) {
return -1; // malformed number, incorrect thousands grouping
}
elseif ($p > 0 && strlen($n) != 3) {
return -1; // malformed number, incorrect thousands grouping
}
$value += $n * pow(10, 3 * (count($num[0]) - 1 - $p));
}
return (float) ($value + $decimal_part / pow(10,strlen($decimal_part)));
}
}
}
功能检查编号($number){
如果((int)substr($number,0,1)==0){
返回false;//不以大于0的数字开头
}
如果((字符串)substr($number,-1)!=“0”&(int)substr($number,-1)==0){
返回false;//不以数字结尾
}
preg_match_all(“/([^0-9]{2,})/”,$number,$sep,preg_模式顺序);
如果(isset($sep[0][0])){
返回false;//多个连续的非数字字符
}
preg_match_all('/([^0-9]{1})/',$number,$sep,preg_模式顺序);
if(count($sep[0])>2&&count(array_unique($sep[0]))>2){
返回false;//两个以上的分隔符
}
其他(计数($sep[0])>2){
$last_sep=array_pop($sep[0]);
if(!in_数组($last_sep,array(“.”,“,”)){
返回false;//不允许将分隔符作为最后一个分隔符
}
$sep_unique=数组_unique($sep[0]);
如果(计数($sep_unique)>1){
return false;//并非所有分隔符(最后一个除外)都相同
}
elseif(!in_数组($sep_unique[0],数组(“'”,“,”,“,”)){
返回false;//不允许使用分隔符
}
}
返回true;
}
函数转换\u编号($number){
preg_match_all(“/([0-9]+)/”,$number,$num,preg_模式顺序);
preg_match_all('/([^0-9]{1})/',$number,$sep,preg_模式顺序);
如果(计数($sep[0])==0){
//无分隔符,整数
返回值(整数)$num[0][0];
}
elseif(计数($sep[0])==1){
//一个分隔符,查找最后一个数字列
if(strlen($num[0][1])==3){
if(strlen($num[0][0])3){
//必须是小数点
返回(浮动)($num[0][0]+$num[0][1]/1000);
}
}
否则{
//必须是小数点
返回(浮动)($num[0][0]+$num[0][1]/pow(10,strlen($num[0][1]));
}
}
否则{
//多个分隔符,先检查后检查
如果($sep[0][0]==end($sep[0])){
//相同的字符,只有数千个分隔符,检查格式良好的NUM
$value=0;
foreach($num[0]为$p=>$n){
如果($p==0&&strlen($n)>3){
return-1;//数字格式错误,分组不正确
}
elseif($p>0&&strlen($n)!=3){
return-1;//数字格式错误,分组不正确
}
$value+=$n*pow(10,3*(计数($num[0])-1-$p));
}
返回值(整数)$value;
}
否则{
//混合字符、千位分隔符和小数点
$decimal_part=array_pop($num[0]);
$value=0;
foreach($num[0]为$p=>$n){
如果($p==0&&strlen($n)>3){
return-1;//数字格式错误,分组不正确
}
elseif($p>0&&strlen($n)!=3){
return-1;//数字格式错误,分组不正确
}
$value+=$n*pow(10,3*(计数($num[0])-1-$p));
}
返回(浮动)($value+$