У меня есть форма, где пользователи пишут разные цифры и могут быть десятичными, но формат отличается от формата по умолчанию PHP и MySQL. Это формат, с которым я работаю:
1,1 (одна точка одна) — 1 000,90 (одна тысяча 90) — 1 000 000,90 (один миллион 90) и т. Д.
Прямо сейчас у меня есть эта функция:
function formato_num($num){
$num = str_replace('.', '', $num);
$num = str_replace(',', '.', $num);
return $num;
}
В этих случаях он работает нормально, но если пользователь по какой-то причине записывает десятичную точку с точкой (.), Он не работает.
У меня есть эта другая функция, но она работает не совсем нормально:
if(strpos($_POST['num'],'.') !== false){
$decimal = $_POST['num'];
$split = explode('.', $decimal);
$l = strlen($split[1]);
if($l < 3){
echo str_replace('.', ',', $_POST['num']);
}else{
$num = str_replace('.', '', $_POST['num']);
$num = str_replace(',', '.', $_POST['num']);
echo $num;
}
}
Любая помощь? Благодарю.
ПРИМЕРЫ:
Если пользователь пишет:
1.000 (одна тысяча) я сохраняю его на DDBB как 1000.
1,2 (десятичный) я сохраняю как 1.1.
Проблема в том, что пользователь использует точку для разделителя тысяч и десятичную дробь.
Вы можете «легко» преобразовать строки, содержащие и запятую, и точку, но особенно если вы хотите поддерживать неупорядоченные разделители тысяч или позволить пользователю вводить три знака после запятой, возникают неясности.
Это наилучший подход, который вы можете использовать. Я пока не несу ответственности за любые неверно истолкованные цифры!
function stringToNumber($str) {
$last_comma = strrpos($str, ',');
$last_dot = strrpos($str, '.');
if($last_comma === false && $last_dot === false) {
return $str;
} elseif($last_comma !== false && $last_dot !== false) {
if($last_comma < $last_dot) {
// dot is further to the right
return str_replace(',', '', $str);
} else {
// comma is further to the right
return str_replace(',', '.', str_replace('.', '', $str));
}
} elseif ($last_dot !== false) {
// No commas. For thousand-separator the following must hold
if(preg_match('/^[0-9]{1,3}(\\.[0-9]{3})+$/', $str)) {
// every dot is followed by three digits... lets assume the user wanted them as thousand-separators
// For a single dot this assumption may be invalid, but we expect the user to use . as thousand-separator...
return str_replace('.', '', $str);
} else {
// We could check here how many dots are used.
return $str;
}
} else {
// No dots. For thousand-separator the following must hold
if(preg_match('/^[0-9]{1,3}(,[0-9]{3})+,[0-9]{3}$/', $str)) {
// every comma is followed by three digits and there are at least two of them
return str_replace(',', '', $str);
} else {
// So this is it. Single comma. We could check if the comma is followed by three digits, but it still could be legitimate and while we want to support unexpected input we do not want to interfere with valid input like "1,234" meant as 1.234
return str_replace(',', '.', $str);
}
}
}
Примеры:
function formated_test($str) {
$num = stringToNumber($str);
printf("% 14s => % 14s\n", $str, $num);
}
formated_test("42");
formated_test("42.1");
formated_test("42,1");
formated_test("42.123");
formated_test("42,123");
formated_test("42.123,42");
formated_test("42,123.42");
formated_test("42.123.456");
formated_test("42,123,456");
formated_test("42.123.456,12");
formated_test("42,123,456.12");
И вывод:
42 => 42 42.1 => 42.1 42,1 => 42.1 42.123 => 42123 42,123 => 42.123 42.123,42 => 42123.42 42,123.42 => 42123.42 42.123.456 => 42123456 42,123,456 => 42123456 42.123.456,12 => 42123456.12 42,123,456.12 => 42123456.12
Других решений пока нет …