Cómo detectar un número de coma flotante usando una expresión regular

¿Cuál es una buena expresión regular para manejar un número de punto flotante (es decir, como Float de Java)?

La respuesta debe coincidir con los siguientes objectives:

1) 1. 2) .2 3) 3.14 4) 5e6 5) 5e-6 6) 5E+6 7) 7.e8 8) 9.0E-10 9) .11e12 

En resumen, debería

  • ignorar los signos anteriores
  • requiere que el primer carácter a la izquierda del punto decimal sea distinto de cero
  • permitir 0 o más dígitos en cualquier lado del punto decimal
  • permitir un número sin un punto decimal
  • permitir la notación científica
  • permitir mayúsculas o minúsculas ‘e’
  • permitir exponentes positivos o negativos

Para aquellos que se preguntan, sí, este es un problema de tarea. Recibimos esto como una tarea en mi clase graduada de CS sobre comstackdores. Ya entregué mi respuesta para la clase y la publicaré como respuesta a esta pregunta.

[Epílogo] Mi solución no recibió crédito completo porque no manejaba más de 1 dígito a la izquierda del decimal. La asignación mencionó el manejo de flotantes Java aunque ninguno de los ejemplos tenía más de 1 dígito a la izquierda del decimal. Publicaré la respuesta aceptada en su propia publicación.

Simplemente haga que tanto el punto decimal como la parte E-then-exponent sean opcionales:

 [1-9][0-9]*\.?[0-9]*([Ee][+-]?[0-9]+)? 

No veo por qué no quieres un líder [+-]? para capturar un posible signo también, pero, lo que sea! -)

Edición : de hecho, ¡puede que no queden dígitos del punto decimal (en cuyo caso imagino que debe haber un punto decimal y más de un dígito después!), Por lo que se necesita una barra vertical (alternativa):

 (([1-9][0-9]*\.?[0-9]*)|(\.[0-9]+))([Ee][+-]?[0-9]+)? 

[Esta es la respuesta del profesor]

Definir:

N = [1-9]
D = 0 | norte
E = [eE] [+ -]? D +
L = 0 | (ND *)

Luego, los números de coma flotante se pueden combinar con:

((L. D * |. D +) E?) | (LE)

También era aceptable usar D + en lugar de L, y anteponer [+ -] ?.

Un error común fue escribir D *. D *, pero esto puede coincidir solo con ‘.’.

[Editar]
Alguien preguntó por un signo principal; Debería haberle preguntado por qué fue excluido, pero nunca tuve la oportunidad. Como esto fue parte de la conferencia sobre gramáticas, creo que o facilitó el problema (no es probable) o hay un pequeño detalle en el análisis en el que divide el conjunto de problemas de manera que el valor del punto flotante, independientemente del signo, es el foco (posible).

Si está analizando a través de una expresión, por ejemplo

-5.04e-10 + 3.14159E10

el signo del valor del punto flotante es parte de la operación que se aplicará al valor y no un atributo del número mismo. En otras palabras,

restar (5.04e-10)
agregar (3.14159E10)

para formar el resultado de la expresión. Aunque estoy seguro de que los matemáticos pueden discutir el punto, recuerden que esto fue de una conferencia sobre análisis sintáctico.

Aquí es lo que entregué.

 (([1-9]+\.[0-9]*)|([1-9]*\.[0-9]+)|([1-9]+))([eE][-+]?[0-9]+)? 

Para facilitar la discusión, etiquetaré las secciones

 ( ([1-9]+ \. [0-9]* ) | ( [1-9]* \. [0-9]+ ) | ([1-9]+)) ( [eE] [-+]? [0-9]+ )? -------------------------------------------------------- ----------------------  AB 

A: coincide con todo hasta el ‘e / E’
B: coincide con la notación científica

Rompiendo A obtenemos tres partes

  ( ([1-9]+ \. [0-9]* ) | ( [1-9]* \. [0-9]+ ) | ([1-9]+) ) ----------1---------- ---------2---------- ---3---- 

Parte 1: permite 1 o más dígitos de 1 a 9, decimales, 0 o más dígitos después del decimal (objective 1)
Parte 2: permite 0 o más dígitos de 1-9, decimales, 1 o más dígitos después del decimal (objective 2)
Parte 3: permite 1 o más dígitos del 1 al 9 sin ningún decimal (ver # 4 en la lista de objectives)


Al dividir B obtenemos 4 partes básicas

  ( [eE] [-+]? [0-9]+ )? ..--1- --2-- --3--- -4- .. 

Parte 1: requiere ‘e’ en mayúscula o minúscula para la notación científica (por ejemplo, los objectives 8 y 9)
Parte 2: permite un signo positivo o negativo opcional para el exponente (por ejemplo, los objectives 4, 5 y 6)
Parte 3: permite 1 o más dígitos para el exponente (objective 8)
Parte 4: permite que la notación científica sea opcional como grupo (objective 3)

 '([-+])?\d*(\.)?\d+(([eE]([-+])?)?\d+)?' 

Esa es la expresión regular a la que he llegado cuando bash resolver este tipo de tarea en Matlab. En realidad, no detectará correctamente números como (1.) pero algunos cambios adicionales pueden resolver el problema … bueno, tal vez lo siguiente lo solucionaría:

 '([-+])?(\d+(\.)?\d*|\d*(\.)?\d+)(([eE]([-+])?)?\d+)?' 

@Kelly S. French: el letrero falta porque en un analizador se agregaría por la expresión unitaria negativa (negación), por lo tanto no es necesario ser detectado como parte de un flotante.

@Kelly S. French, esta expresión regular coincide con todos los casos de prueba.

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

Fuente: perldoc perlretut