2010-12-18 62 views

Respuesta

2

El standard library function strtod maneja el componente exponencial bien (lo mismo ocurre con atof, pero strtod le permite diferenciar entre un análisis sintáctico fallado y analizar el valor cero).

5

una expresión regular que funciona bastante bien sería:

-?[\d.]+(?:e-?\d+)? 

Conversión a un número se puede hacer así: String in scientific notation C++ to double conversion, supongo.

la expresión regular es

-?  # an optional - 
[\d.]+ # a series of digits or dots (see *1) 
(?:  # start non capturing group 
    e  # "e" 
    -? # an optional - 
    \d+ # digits 
)?  # end non-capturing group, make optional 

** 1) Esto no es 100% correcto, técnicamente no puede haber un único punto, y antes de que sólo uno (o no) dígitos. Pero, en la práctica, esto no debería suceder. Entonces, la expresión regular es una buena aproximación y los falsos positivos deberían ser muy poco probables. Siéntase libre de hacer que la expresión regular sea más específica. *

+1

Sugiero dividir el '[\ d.] +' En '\ d + \. \ D +' para evitar coincidencias falsas. Use '\ d *' si no necesita dígitos antes y/o después del punto decimal. – marcog

+0

IS que no va a coincidir con '5.5.5.5.5.5.5.5.5.5.5.5.5' –

+0

@Martin: Sí, lo es. La pregunta es: ¿Es probable que suceda tal valor? Si es así, la expresión regular puede hacerse más específica. Mi suposición sería que el escenario '5.5.5.5' es bastante improbable en estas circunstancias. – Tomalak

2

Puede identificar los valores científicos usando: -?\d*\.?\d+e[+-]?\d+ regex.

+1

Nunca use '{0,1}' -use '?' En su lugar. El primero es más largo, no más claro, y tiene un efecto idéntico. –

+0

'{0,1}' se puede reemplazar por '?'. Pero, ¿por qué quieres que el punto decimal sea opcional? Y esto no permite números negativos. También coincide falsamente con '.0', que probablemente no sea el deseado. – marcog

+0

@marcog: Probablemente porque según los datos de ejemplo, el punto decimal ES opcional. El tercer campo es simplemente "1". –

2

Si usted puede estar seguro de que el formato de la doble es científica, puede intentar algo como lo siguiente:

string inp("8.67548e-017"); 
    istringstream str(inp); 
    double v; 
    str >> scientific >> v; 
    cout << "v: " << v << endl; 

Si desea detectar si hay un número de coma flotante de ese formato, entonces las expresiones rectas anteriores harán el truco.

EDIT: En realidad no es necesario el manipulador scientific, al transmitir en un doble, lo hará de forma automática el manejo para usted (ya sea fijo o científica)

+0

Creo que este es el camino a seguir para C++. juguetear con expresiones regulares que a veces funcionan y otras no, no sería la manera ideal para mí. en su lugar, esto delega la parte aproximada al stringstream de stl. esta es la versión de nivel superior para verificar un formato científico válido. –

0

Bueno esto no es exactamente lo que usted pidió ya no es Perl (gak) y es una definición regular, no una expresión regular, pero es lo que uso para reconocer una extensión de C literales de coma flotante (la extensión permite "_" en cadenas de dígitos), estoy seguro se puede convertir a una expresión regular ilegible si quieres:

/* floats: Follows ISO C89, except that we allow underscores */ 
let decimal_string = digit (underscore? digit) * 
let hexadecimal_string = hexdigit (underscore? hexdigit) * 

let decimal_fractional_constant = 
    decimal_string '.' decimal_string? 
    | '.' decimal_string 

let hexadecimal_fractional_constant = 
    ("0x" |"0X") 
    (hexadecimal_string '.' hexadecimal_string? 
    | '.' hexadecimal_string) 

let decimal_exponent = ('E'|'e') ('+'|'-')? decimal_string 
let binary_exponent = ('P'|'p') ('+'|'-')? decimal_string 

let floating_suffix = 'L' | 'l' | 'F' | 'f' | 'D' | 'd' 
let floating_literal = 
    (
    decimal_fractional_constant decimal_exponent? | 
    hexadecimal_fractional_constant binary_exponent? 
) 
    floating_suffix? 

formato C está diseñado para langu programación las edades no los datos, por lo que puede apoyar cosas que su entrada no requiere.

0

Probé varias de las otras soluciones en vano, así que se me ocurrió esto.

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

Regular expression visualization

Debuggex Demo

nada que coincida es considerado como notación científica válida.

Tenga en cuenta: Esto acepta e+, e- y e; si no desea aceptar e, utilice esto: ^(-?\d+)\.?\d+(e-|e\+|\d+)\d+$

No estoy seguro de si funciona para C++, pero en C# puede agregar (?i) entre el ^ y (- en la expresión regular, para alternar en línea case-insensitivity. Sin él, los exponentes declarados como 1.05E+10 no serán reconocidos.

Edit: Mi expresión regular anterior era un poco problemática, así que la he reemplazado por la anterior.

Cuestiones relacionadas