いくつかの組み込み PHP 関数を使用して簡単な解決策を見つけることができなかったので、(1) 入力された文字列が数値であるかどうかを確認するための 2 つの関数を作成しました。使用されるセパレーター。
千単位の区切り記号として、可能な区切り文字をピリオド ( .
)、コンマ ( ,
)、スペース (
)、およびアポストロフィ ( )に制限しました。'
小数点は、最初の 2 つのオプションの 1 つだけです。セパレーターの両方のセットを編集して、さらに多くのセパレーターを許可したり、所定の位置にあるものを制限したりできます。
私が実際に行っているのは、いくつかの単純なpreg_match_all
呼び出しを使用して、すべての数値列とすべての区切り記号を探すことです。
完全なコードは次のようになりますfalse
。確かに、これは何らかの形で単純化できると思いますが、現在は機能しており、多くのエラーをフィルタリングしながら、2 000 000.25
またはなどの奇妙な組み合わせも許可してい2'000'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)));
}
}
}
この一連の関数にある 1 つの欠陥を認識しています: 1.234
or1,234
は常に整数として扱われます1234
。関数は、1 つの区切り記号の前に 4 桁未満の桁がある場合、区切り記号が千単位の区切り記号である必要があると想定しているためです。