БлогNot. Регулярное выражение для проверки правильности записи вещественного числа

Регулярное выражение для проверки правильности записи вещественного числа

Проверка правильности записи вещественного числа с помощью регулярного выражения PHP - не такая простая задача, какой она может показаться на первый взгляд. Введём следующее выражение (используется синтаксис PCRE):

/^(?:\+|\-)?\d+(?:\.\d+)?(?:e(?:\+|\-)?\d+)?$/i

Этот regexp скажет "да", если входная строка является допустимой записью вещественного числа. Здесь и далее регулярные выражения приведены в виде строки, которую можно использовать первым аргументом функции preg_match или preg_match_all, то есть, показанную выше строку нужно лишь заключить в двойные кавычки.

Увы, такое выражение не разрешает числа вроде -1. или .5, запись которых разрешена в некоторых языках программирования. Так что пришлось написать несколько более сложное регулярное выражение:

/^(?:\+|\-)?(?:(?:\d+)|(?:\d+\.)|(?:\.\d+)|(?:\d+\.\d+)){1}(?:e(?:\+|\-)?\d+)?$/i

Регулярное выражение удалось составить только "на всю строку" (шаблон начинается с метки начала строки ^ и заканчивается меткой конца $), так что сначала бьём входные данные на лексемы, тоже с помощью регулярного выражения вида [\s,]+ (оно означает "разделитель или запятая").

Чтобы не зависеть от регистра символа "e", оба выражения сделаны регистронезависимыми с помощью модификатора шаблона /i.

Примеры из тестового прогона скрипта:

Array ( [0] => -11e1 [1] => 2.3-e3 [2] => 2.1E-02 [3] => 14e [4] => 12e2e2 [5] => 1E3 [6] => 1E-2 [7] => 1.4.5 [8] => 1-3 [9] => 1.3 [10] => -1.5 [11] => -2.5e-02 [12] => -1e-06 [13] => 1EE2 [14] => 1.01E003 [15] => -1. [16] => .5 [17] => . [18] => .e10 [19] => e1 [20] => -e5. [21] => 2.E1 [22] => .5e3 )
Всего элементов: 23
Элемент 1 (-11e1): число -11e1
Элемент 2 (2.3-e3): не число
Элемент 3 (2.1E-02): число 2.1E-02
Элемент 4 (14e): не число
Элемент 5 (12e2e2): не число
Элемент 6 (1E3): число 1E3
Элемент 7 (1E-2): число 1E-2
Элемент 8 (1.4.5): не число
Элемент 9 (1-3): не число
Элемент 10 (1.3): число 1.3
Элемент 11 (-1.5): число -1.5
Элемент 12 (-2.5e-02): число -2.5e-02
Элемент 13 (-1e-06): число -1e-06
Элемент 14 (1EE2): не число
Элемент 15 (1.01E003): число 1.01E003
Элемент 16 (-1.): число -1.
Элемент 17 (.5): число .5
Элемент 18 (.): не число
Элемент 19 (.e10): не число
Элемент 20 (e1): не число
Элемент 21 (-e5.): не число
Элемент 22 (2.E1): число 2.E1
Элемент 23 (.5e3): число .5e3

 Выполнить этот тестовый вызов онлайн

 Перейти к онлайн-сервису для проверки вещественных чисел

Вот исходник основной части скрипта (может измениться в онлайн-версии):

<?php 
 $data='';
 if (isset($_GET['data'])) $data = strip_tags(trim($_GET['data']));
 if (!isset($_GET['submit'])) {
  echo '<form method="get" action="'.$_SERVER['PHP_SELF'].'">
   <input type="text" name="data" maxlength="128" size="128" value="'.$data.'">
   <input type="submit" name="submit" value="OK"></form>';
 } 
 else {
  $array = preg_split ("/[\s,]+/",$data);
  print_r ($array);
  echo '<br>Всего элементов: '.count($array);
  $k=0;
  foreach ($array as $d) {
   echo '<br>Элемент '.++$k.' (<font color="red">'.$d.'</font>): ';
   $res=preg_match( 
    "/^(?:\+|\-)?(?:(?:\d+)|(?:\d+\.)|(?:\.\d+)|(?:\d+\.\d+)){1}(?:e(?:\+|\-)?\d+)?$/i",$d);
   if ($res===false) echo 'ошибка в регулярном выражении!';
   elseif ($res===0) echo 'не число';
   else echo 'число '.$d;
  }
  echo '<br><a href="'.$_SERVER['PHP_SELF'].'?data='.urlencode($data).'">Вернуться</a>';
 }  
?>

Думаю, этот код может служить и примером организации небольшого сервиса, проверяющего вводимые пользователем строки на соответствие некоторому шаблону.

 Ещё более простой код решения этой задачи без регулярных выражений

P.S. Позднее для проверки утверждения "Вся строка в Юникоде является вещественным числом" я пользовался вот таким регулярным выражением:

"/^(\+|\-)?(\d+\.?|\.\d+|\d+\.\d+)([eE](\+|\-)?\d+)?$/u"

 Мой сервис для проверки регулярных выражений онлайн

02.04.2013, 13:13 [15525 просмотров]


теги: php сервис textprocessing числа

К этой статье пока нет комментариев, Ваш будет первым