2009-09-15 11 views
8

Sto cercando uno strumento diff che può anche confrontare i valori in virgola mobile (con una certa tolleranza) nei file di testo. Questo è in aggiunta alle tipiche funzioni di confronto testo-confronto, con opzioni per ignorare gli spazi bianchi, ignorare le maiuscole, ecc. Una GUI (o interfaccia utente della console a schermo intero) va bene, ma preferirei un flusso orientato (stdin/stdout) strumento.Strumento differenziale che ignora i formati in virgola mobile (ma non i valori) nel testo?

Ecco un esempio estremamente semplice che caratterizza lo strumento ideale. Ci sono 2 versioni di 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; 
} 

Ed ecco l'output di diff che ci si aspetta:

$ 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 */ 

Il secondo diff (riga 8) è la normale differenza di testo; il primo diff (riga 6) è dovuto al fatto che i numeri sono al di fuori della tolleranza specificata. (L'esponente dovrebbe essere 16, non 18, quindi è spento di 100.0X).

Nota che nessuna delle altre modifiche in virgola mobile viene visualizzata come differenza — anche se si tratta di modifiche di testo, i valori in virgola mobile non cambiano oltre la tolleranza specificata.

C'è uno strumento diff in grado di fare ciò?

In caso contrario, c'è qualcosa di simile, è open source?

risposta

5

C'è questo, che sembra molto interessante. Sto cercando di farlo lavorare sul mio AIX, così non ho sembrare in azione ancora, ma credo che questo è quello che voi (e io :-) bisogno

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

+0

Wow! L'output è ** esattamente ** quello che volevo! Btw, la versione di BeOS [http://www.bebits.com/app/3784] compilata sotto Cygwin senza modifiche. –

+0

Beh, non riesco ancora a farlo funzionare su AIX. Su Linux, gcc-3.3.3 lo ha compilato, ma segfault sul primo "spiff Sample.1 Sample.2". Su una macchina nuova, gcc-4.2.4 è arrabbiato per: spiff.c: 178: errore: la dichiarazione statica di "_Y_doargs" segue la dichiarazione non statica spiff.c: 30: errore: la precedente dichiarazione di "_Y_doargs" era qui – Davide

+0

@Davide: se sei ancora bloccato, forse dovresti fare una domanda al riguardo su qualche sito web da qualche parte. ;-) –

0

Non sono a conoscenza di tale strumento, ma sarebbe abbastanza facile generare uno script Perl per farlo per voi combinando un po 'di espressioni regolari in virgola mobile con una serie di routine per normalizzare detti flog regexati. Potrei probabilmente darci un colpetto se hai bisogno di aiuto, ma è un'impresa un po 'dispendiosa in termini di tempo, quindi sarò un porco avido e chiederò un'utile taglia.

+0

Grazie per la vostra offerta. In realtà ho cercato di scrivere il mio strumento per questo, ma non sono convinto che le regex siano sufficienti per confronti all'interno di una tolleranza specificata. –

+0

Se si tira la nostra, ciò che si vuole fare è quello di utilizzare Math :: gerarchia biblioteca (Math :: BigFloat credo), eventualmente abbinato con il miglior espressione regolare in virgola mobile si possono trovare su CPAN o costruire da soli - il libro Perl Regexp ne ha alcuni carini. Se sei fortunato, Math :: hierarchy ha il suo parser (non usarlo per un po ', quindi non ricordare). – DVK

+0

Una regexp non può essere piegata ragionevolmente per calcolare le tolleranze. È necessario convertire i valori in flottanti della macchina e confrontarli. –

1

Vedi Smart Differencer Tools. Questi strumenti confrontano due file di codice sorgente in base alla struttura del programma, anziché confrontare le righe di testo. Per fare ciò, questi strumenti analizzano il file sorgente in base alle regole della lingua, creano un AST e confrontano gli alberi. L'output è in termini di modifiche al montaggio astratto (inserire, eliminare, spostare, copiare, rinominare) in strutture del programma (identificatori, espressioni, istruzioni, blocchi, metodi, ...).

Come effetto collaterale, i singoli lessemi di lingua, come caratteri, stringhe e valori letterali numerici, vengono convertiti in una rappresentazione interna di forma normale. Il formato letterale viene ignorato, quindi tratterà i valori in virgola mobile come 00.001 e 1e-03 come identici, 0xFF e 255 come identici, e "\ n" e "\ u000a" come identici. Questo non include un fuzz di tolleranza per i numeri in virgola mobile, ma ignora la loro forma.Ciò significa che gli strumenti di SmartDifference riporteranno due numeri corrispondenti ma leggermente diversi come diversi, ma segnaleranno solo i numeri stessi; si otterrà qualcosa di simile

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

Il matcher permette attualmente identificatori di essere diversi e tratta un identificatore coerente ridenominazione in un ambito come una singola modifica, piuttosto che un gruppo di diverse modifiche. L'idea di utilizzare fuzz a virgola mobile per consentire la corrispondenza dei numeri fp near-miss è interessante; Lo aggiungerò alla lista delle possibili richieste di funzionalità.

Questi strumenti sono di produzione per Java, COBOL e C#. Abbiamo versioni di pre-produzione per C++ e C; il difficile problema è il reperimento di strutture di programmi per linguaggi che consentono in effetti un editing arbitrario della souce tramite l'uso di macro e condizionali del preprocessore.

+0

Sicuramente un passo nella direzione che volevo, e dannatamente bello. Sono curioso di sapere come la "rappresentazione interna" possa confrontare i valori in virgola mobile senza una tolleranza. Suppongo che se sei vincolato a valori letterali (al contrario dei risultati del calcolo), la tolleranza non è strettamente necessaria. Ma non sarebbe una caratteristica elegante? ;-) –

+0

@system PAUSE: confrontare "rappresentazioni interne" è facile. Prendi il valore in virgola mobile e confrontalo con l'altro per l'uguaglianza. Questo non è diverso rispetto al confronto di identificatori o stringhe letterali. –

Problemi correlati