Как определить число с плавающей запятой, используя регулярное выражение
Что такое хорошее регулярное выражение для обработки числа с плавающей запятой (например, Java Float)
Ответ должен соответствовать следующим целям:
1) 1.
2) .2
3) 3.14
4) 5e6
5) 5e-6
6) 5E+6
7) 7.e8
8) 9.0E-10
9) .11e12
Таким образом, он должен
- игнорировать предыдущие знаки
- требуется, чтобы первый символ слева от десятичной точки был ненулевым
- разрешить 0 или более цифр по обе стороны от десятичной точки
- разрешить число без десятичной точки
- разрешить научную нотацию
- разрешить капитальные или строчные буквы 'e'
- разрешить положительные или отрицательные показатели
Для тех, кто задается вопросом, да, это проблема домашних заданий. Мы получили это как задание в моем классе CS для выпускников в компиляторах. Я уже включил свой ответ для класса и опубликую его как ответ на этот вопрос.
[Послесловие]
Мое решение не получило полного кредита, потому что оно не обрабатывало более 1 цифры слева от десятичной дроби. В задании упоминалось обращение к поплавкам Java, хотя ни один из примеров не имел более 1 цифры слева от десятичной. Я опубликую принятый ответ в его собственном сообщении.
Ответы
Ответ 1
[Это ответ от профессора]
Определение:
N = [1-9]
D = 0 | N
E = [eE] [+ -]? D +
L = 0 | (N D *)
Затем числа с плавающей запятой могут быть сопоставлены с:
((L. D * |. D +) E?) | (L E)
Было также приемлемо использовать D +, а не L, и добавить [+ -]?.
Общей ошибкой было написать D *. D *, но это может совпадать с ".".
[Изменить]
Кто-то спросил о ведущем знаке; Я должен был спросить его, почему это было исключено, но так и не получилось. Поскольку это было частью лекции по грамматике, я предполагаю, что либо это сделало проблему более простой (маловероятной), либо была небольшая деталь в синтаксическом разборе, где вы делите набор проблем, так что значение с плавающей запятой, независимо от знака, равно фокус (возможно).
Если вы разбираете выражение, например.
-5.04e-10 + 3.14159E10
знак значения с плавающей запятой является частью операции, применяемой к значению, а не атрибутом самого числа. Другими словами,
вычесть (5.04e-10)
добавить (3.14159E10)
чтобы сформировать результат выражения. Хотя я уверен, что математики могут спорить об этом, помните, что это было из лекции по разбору.
Ответ 2
Просто сделайте как десятичную точку, так и часть E-then-exponent необязательной:
[1-9][0-9]*\.?[0-9]*([Ee][+-]?[0-9]+)?
Я не понимаю, почему вы не хотите, чтобы ведущий [+-]?
мог захватить возможный знак, но, что угодно! -)
Изменить: на самом деле не может быть цифр слева от десятичной точки (в этом случае я полагаю, что после него должна быть десятичная точка и 1 + цифры!), поэтому вертикальная панель (альтернативный вариант):
(([1-9][0-9]*\.?[0-9]*)|(\.[0-9]+))([Ee][+-]?[0-9]+)?
Ответ 3
http://www.regular-expressions.info/floatingpoint.html
Ответ 4
Вот что я включил.
(([1-9]+\.[0-9]*)|([1-9]*\.[0-9]+)|([1-9]+))([eE][-+]?[0-9]+)?
Чтобы упростить обсуждение, я назову разделы
( ([1-9]+ \. [0-9]* ) | ( [1-9]* \. [0-9]+ ) | ([1-9]+)) ( [eE] [-+]? [0-9]+ )?
-------------------------------------------------------- ----------------------
A B
A: соответствует всем параметрам "e/E"
B: соответствует научной нотации
Разрушение A мы получаем три части
( ([1-9]+ \. [0-9]* ) | ( [1-9]* \. [0-9]+ ) | ([1-9]+) )
----------1---------- ---------2---------- ---3----
Часть 1: разрешает 1 или более цифр от 1 до 9, десятичную, 0 или более цифр после десятичной (цель 1)
Часть 2: Позволяет 0 или более цифр от 1 до 9, десятичной, 1 или более цифр после десятичной (цель 2)
Часть 3: Позволяет 1 или более цифр от 1 до 9 без десятичной (см. № 4 в списке целей)
Разбивая B, мы получаем 4 основные части
( [eE] [-+]? [0-9]+ )?
..--1- --2-- --3--- -4- ..
Часть 1: требует ввода верхнего или нижнего регистра "e" для научной нотации (например, целей 8 и 9)
Часть 2: допускает необязательный положительный или отрицательный знак для экспоненты (например, цели 4, 5 и 6)
Часть 3: разрешает 1 или более цифр для экспонента (цель 8)
Часть 4: позволяет научной нотации быть необязательной в качестве группы (цель 3)
Ответ 5
'([-+])?\d*(\.)?\d+(([eE]([-+])?)?\d+)?'
Это регулярное выражение, к которому я пришел при попытке решить эту задачу в Matlab. Фактически, он не будет правильно определять числа, подобные (1.), но некоторые дополнительные изменения могут решить проблему... ну, может быть, следующее исправит это:
'([-+])?(\d+(\.)?\d*|\d*(\.)?\d+)(([eE]([-+])?)?\d+)?'
Ответ 6
@Kelly S. French: знак отсутствует, поскольку в синтаксическом анализаторе он добавляется унарным минусом (отрицанием), поэтому его необязательно обнаруживать как часть float.
Ответ 7
@Kelly S. French, это регулярное выражение соответствует всем вашим тестовым случаям.
^[+-]?(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?$
Источник: perldoc perlretut