2010-02-19 47 views
12

¿Qué es una buena expresión regular para el manejo de un número de coma flotante (es decir, como flotador de Java)Cómo detectar un número de coma flotante utilizando una expresión regular

La respuesta debe coincidir con arreglo a los siguientes objetivos:

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, se debe

  • ignorar las señales anteriores
  • requieren el primer carácter a la izquierda de el punto decimal a ser distinto de cero
  • permiten 0 o más dígitos a cada lado del punto decimal
  • permitir un número sin la coma decimal
  • permiten notación científica
  • permitir que el capital o minúscula 'e'
  • permiten exponentes positivos o negativos

Para aquellos que se preguntan, sí, esto es un problema de tarea. Recibimos esto como una tarea en mi clase graduada de CS sobre compiladores. 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.

+0

que personalmente iba a escribir un montón de pruebas unitarias ... –

+0

Estos son requisitos muy extrañas. Dicha expresión no coincidirá con "0.5". – user763305

Respuesta

7

[Esta es la respuesta del profesor] ​​

Definir:

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

números de punto flotante A continuación, se pueden combinar con: (..? (L * D | D +) E)

| (L E)

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

Un error común era escribir D *. D *, pero esto puede coincidir solo con '.'.

[Editar]
Alguien preguntó acerca de un letrero 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 usted 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 en sí. En otras palabras,

restar (5.04e-10)
add (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.

+0

¿Qué hay de Infinity y NaN? –

+0

Dado que el ejercicio consistía en analizar un lenguaje, me atrevo a aventurar que la gramática necesitaría definir tokens que representen esos conceptos suponiendo que están permitidos como entrada. –

23

Simplemente haga tanto el punto decimal y la parte E-entonces-exponente opcional:

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

no veo por qué no quiere un líder [+-]? para capturar una posible señal también, pero, lo que sea -)

Editar:! que podría ser, de hecho no hay dígitos a la izquierda del punto decimal (en cuyo caso me imagino que debe ser el punto decimal y 1+ dígitos después de él) por lo que, una barra vertical (alternativa) i s claramente necesario:

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

Tenga en cuenta que esto no coincide con nada de la forma '.x' o' 0.x'. –

+4

@Alex: Es posible que no desee capturar el signo en caso de que sea parte de una expresión, como en "5-2.5". Eso se espera si estás tokenizando cosas, como lo harías al escribir un compilador. –

+0

@Anon, derecha: '0.x' debe ser rechazado por la segunda regla. –

2

Esto es lo que entregué.

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

Para que sea más fácil hablar, voy a etiquetar la secciones

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

A: partidos todo hasta el 'E/E'
B: coincide con la notación científica

Romper A obtenemos tres partes

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

parte 1: permite a 1 o r más dígitos del 1 al 9, decimal, 0 o más dígitos después del decimal (objetivo 1)
Parte 2: permite 0 o más dígitos del 1 al 9, decimal, 1 o más dígitos después del decimal (objetivo 2)
Parte 3: permite a 1 o más dígitos de 1-9 sin decimal (ver # 4 en la lista de objetivos)


El desglose de B obtenemos 4 partes básicas

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

Parte 1: requiere ya sea 'e' en mayúscula o minúscula para notación científica (p. ej. objetivos 8 & 9)
Parte 2: permite a un signo positivo o negativo opcional para el exponente (por ejemplo, objetivos 4, 5, & 6)
Parte 3: permite a 1 o más dígitos para el exponente (objetivo 8)
Parte 4: permite la notación científica para ser opcional como un grupo (objetivo 3)

+0

Su primera parte (1) de (A) no permite' 10.'. – tur1ng

+0

La parte (1) de (A) debería ser '([1-9] [0-9] * \. [0-9] *)'. Se necesita un cambio similar para la parte (3). –

+0

@ tur1ng: cierto, pero culpe a la entrada de prueba! 8-) –

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

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

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

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

1

@Kelly S. Francés, esta expresión regular coincide con todos sus casos de prueba.

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

Fuente: perldoc perlretut

Cuestiones relacionadas