Подтвердить что ты не робот

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

Что такое хорошее регулярное выражение для обработки числа с плавающей запятой (например, 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 цифры слева от десятичной. Я опубликую принятый ответ в его собственном сообщении.

4b9b3361

Ответ 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]+)?

Ответ 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