2009-09-15 26 views
8

Estoy buscando una herramienta diff que también puede comparar valores de coma flotante (dentro de cierta tolerancia) en archivos de texto. Esto es además de las típicas funciones de comparación de texto, con opciones para ignorar espacios en blanco, ignorar mayúsculas y minúsculas, etc. Una GUI (o una interfaz de usuario de consola de pantalla completa) está bien, pero realmente preferiría un flujo orientado (stdin/stdout herramienta)¿Herramienta Diff que ignora los formatos de coma flotante (pero no los valores) en el texto?

Aquí hay un ejemplo extremadamente simple que caracteriza a la herramienta ideal. Hay 2 versiones de foo.c:

foo_v1.c:

#include <stdio.h> 

#define PI  3.14159265359 
#define E_CUBED 20.0855 
#define HALF_PHI 0.809f 
#define C_SQUARED 89875517873681764.0L 

const double AVO = 6.022e23; /* Avocado number */ 

int main() 
{ 
    printf("%g %g %g %Lg %g\n", PI, E_CUBED, HALF_PHI, C_SQUARED, AVO); 
    return 0; 
} 

foo_v2.c:

#include <stdio.h> 

#define PI  3.14159265358979 
#define E_CUBED 2.00855e+1 
#define HALF_PHI 8.09e-1f 
#define C_SQUARED 8.9875517873681764e18L 

const double AVO = 6.022e23; /* Avogadro number */ 

int main() 
{ 
    printf("%g %g %g %Lg %g\n", PI, E_CUBED, HALF_PHI, C_SQUARED, AVO); 
    return 0; 
} 

y aquí está la salida del diff que cabe esperar:

$ diff --floats=byvalue --tolerance=1e-9 foo_v1.c foo_v2.c 
6c6 
< #define C_SQUARED 89875517873681764.0L 
--- 
> #define C_SQUARED 8.9875517873681764e18L 
8c8 
< const double AVO = 6.022e23; /* Avocado number */ 
--- 
> const double AVO = 6.022e23; /* Avogadro number */ 

La segunda diferencia (línea 8) es la diferencia de texto habitual; la primera diferencia (línea 6) se debe a que los números están fuera de la tolerancia especificada. (El exponente debe ser 16, no 18, entonces está apagado por 100.0X).

Tenga en cuenta que ninguno de los otros cambios de punto flotante aparecen como diffs — aunque sean cambios de texto, los valores de punto flotante no cambian más allá de la tolerancia especificada.

¿Hay alguna herramienta de diferencias que pueda hacer esto?

Si no, ¿hay algo cercano, eso es de código abierto?

Respuesta

5

Hay esta, que se ve muy interesante. Estoy tratando de tener que trabajar en mi AIX, así que no he parecen en acción todavía, pero creo que esto es lo que usted (y yo :-) necesita

http://hpux.connect.org.uk/hppd/hpux/Text/spiff-1.0/

+0

¡Guau! ¡La salida es ** exactamente ** lo que quería! Por cierto, la versión BeOS [http://www.bebits.com/app/3784] compilada bajo Cygwin sin cambios. –

+0

Bueno, todavía no puedo hacerlo funcionar en AIX. En Linux, gcc-3.3.3 lo compiló, pero segfault en el primer "spiff Sample.1 Sample.2". En una máquina más nueva, gcc-4.2.4 está enojado por: spiff.c: 178: error: la declaración estática de '_Y_doargs' sigue a la declaración no estática spiff.c: 30: error: la declaración anterior de '_Y_doargs' era aquí – Davide

+0

@Davide: si todavía estás atascado, tal vez deberías hacer una pregunta al respecto en algún sitio web en alguna parte. ;-) –

0

No conozco esta herramienta, pero sería bastante fácil acelerar un script de Perl para que lo haga combinándolo con un conjunto de expresiones regulares de punto flotante con un conjunto de rutinas para normalizar dichos flotantes regexados. Probablemente pueda echarle un vistazo si necesitas ayuda, pero es una empresa que consume mucho tiempo, así que seré un cerdo codicioso y pediré una recompensa útil.

+0

Gracias por su oferta. En realidad, he estado buscando escribir mi propia herramienta para esto, pero no estoy convencido de que las expresiones regulares sean suficientes para comparaciones dentro de una tolerancia especificada. –

+0

Si tira el nuestro, lo que quiere hacer es utilizar la jerarquía de la biblioteca Math :: (Math :: BigFloat creo) posiblemente emparejada con la mejor expresión regular de coma flotante que pueda encontrar en CPAN o construir usted mismo: el libro de Perl Regexp tiene algunos bonitos. Si tiene suerte, la jerarquía Math :: tiene su propio analizador (no lo ha usado por un tiempo, así que no lo recuerde). – DVK

+0

Una expresión regular no se puede doblar razonablemente para calcular las tolerancias. Necesita convertir los valores en flotadores de máquina y compararlos. –

1

Ver Smart Differencer Tools. Estas herramientas comparan dos archivos de código fuente según la estructura del programa, en lugar de comparar líneas de texto. Para hacerlo, estas herramientas analizan el archivo fuente de acuerdo con las reglas del lenguaje, crean un AST y comparan árboles. El resultado es en términos de cambios de edición abstracta (insertar, eliminar, mover, copiar, renombrar) a estructuras de programa (identificadores, expresiones, instrucciones, bloques, métodos, ...).

Como efecto secundario, los lexemas de lenguaje individual, como caracteres, cadenas y literales numéricos, se convierten a una representación interna de forma normal. El formato de literal se ignora, por lo que tratará los valores de punto flotante como 00.001 y 1e-03 como idénticos, 0xFF y 255 como idénticos, y "\ n" y "\ u000a" como idénticos. Esto no incluye una fuzz de tolerancia para los números de coma flotante, pero ignora su forma.Lo que esto significa es que las herramientas SmartDifference reportarán dos números correspondientes pero ligeramente distintos como diferentes, pero solo informará los números ellos mismos; obtendrá algo así como

<Line 75 col 15-19 1.01 
    >replace by Line 75 col 15-19 1.02 

El matcher actualmente permite identificadores sean diferentes y trata de cambiar el nombre de un identificador constante a través de un alcance que una sola edición en lugar de que un montón de diferentes ediciones. La idea de usar fuzz de punto flotante para permitir el emparejamiento de números fp near-miss es interesante; Lo agregaré a la lista de posibles solicitudes de funciones.

Estas herramientas son de producción para Java, COBOL y C#. Tenemos versiones de preproducción para C++ y C; El problema más difícil es seleccionar estructuras de programas para idiomas que permitan de manera efectiva la edición arbitraria de la fuente a través del uso de macros y condicionales de preprocesador.

+0

Definitivamente un paso en la dirección que yo quería, y bastante genial. Tengo curiosidad de cómo la "representación interna" puede comparar valores de coma flotante sin tolerancia. Supongo que si está limitado a los literales (a diferencia de los resultados de cálculo), la tolerancia no es estrictamente necesaria. ¿Pero no sería una característica ingeniosa? ;-) –

+0

@system PAUSA: comparar "representaciones internas" es fácil. Tome el valor del punto flotante binario y compare con el otro para la igualdad. Eso no es diferente a la comparación de identificadores o literales de cadena. –

Cuestiones relacionadas