Domanda

L'applicazione dei miei clienti esporta e importa alcune variabili di tipo reale attraverso un file di testo usando writeln e readln. Ho provato ad aumentare la larghezza dei campi scritti in modo che il codice assomigli a:

writeln(file, exportRealvalue:30); //using excess width of field
....
readln(file, importRealvalue);

Quando esporto e quindi importare ed esportare di nuovo e confrontare i file ottengo una differenza nelle ultime due cifre, ad esempio (potrebbe essere spento sul numero effettivo di cifre qui ma lo ottieni):

-1.23456789012E-0002
-1.23456789034E-0002

Questo in realtà fa la differenza nell'app, quindi il cliente vuole sapere cosa posso fare al riguardo. Ora non sono sicuro che sia solo la scrittura / lettura che lo fa, ma ho pensato di fare una breve domanda prima di immergermi di nuovo nello hey stack. Devo andare binario su questo?

Questa non è un'app che si occupa di valuta o qualcosa del genere, scrivo e leggo solo i valori da / verso il file. So che a volte i punti fluttuanti sono un po 'strani e ho pensato che una delle routine (writeln / readln) potesse avere degli affari divertenti in corso.

È stato utile?

Soluzione

Se si desidera specificare la precisione di un reale con un WriteLn, utilizzare quanto segue:

WriteLn(RealVar:12:3);

Produce il valore Realvar con almeno 12 posizioni e una precisione di 3.

Altri suggerimenti

Potresti provare a passare a esteso per una maggiore precisione. Come è stato sottolineato, tuttavia, i numeri in virgola mobile hanno solo così tante cifre significative di precisione, quindi è ancora possibile visualizzare più cifre quindi essere memorizzate con precisione, il che potrebbe comportare il comportamento specificato.

Dall'aiuto di Delphi:

Tipi reali fondamentali di Win32

                                            | Significant | Size in 
Type     | Range                            | digits      | bytes
---------+----------------------------------+-------------+----------
Real     | -5.0 x 10^–324 .. 1.7 x 10^308   | 15–16       |   8  
Real48   | -2.9 x 10^–39 .. 1.7 x 10^38     | 11-12       |   6   
Single   | -1.5 x 10^–45 .. 3.4 x 10^38     |  7-8        |   4   
Double   | -5.0 x 10^–324 .. 1.7 x 10^308   | 15-16       |   8   
Extended | -3.6 x 10^–4951 .. 1.1 x 10^4932 | 10-20       |  10   
Comp     | -2^63+1 .. 2^63–1                | 10-20       |   8   
Currency | -922337203685477.5808..          |             | 
                    922337203685477.5807    | 10-20       |   8   
  

Nota : il tipo Real48 a sei byte era chiamato Real nelle versioni precedenti di Object Pascal. Se stai ricompilando il codice che utilizza il tipo Real a sei byte più vecchio in Delphi, ti consigliamo di cambiarlo in Real48 . Puoi anche utilizzare la direttiva del compilatore {$ REALCOMPATIBILITY ON} per riportare Real nel tipo a sei byte. Le seguenti osservazioni si applicano ai tipi reali fondamentali.

     
      
  • Real48 viene mantenuto per compatibilità con le versioni precedenti. Poiché il suo formato di archiviazione non è nativo dell'architettura del processore Intel, risulta in prestazioni più lente rispetto ad altri tipi a virgola mobile.
  •   
  • Esteso offre una precisione maggiore rispetto ad altri tipi reali ma è meno portatile. Fare attenzione a utilizzare Esteso se si stanno creando file di dati da condividere su più piattaforme.
  •   

Si noti che l'intervallo è maggiore delle cifre significative. Quindi puoi avere un numero maggiore, quindi puoi memorizzarlo con precisione. Consiglierei di arrotondare alle cifre significative per evitare che ciò accada.

Quando si utilizzano tipi in virgola mobile, è necessario essere consapevoli delle limitazioni di precisione sui tipi specificati. Un tipo IEEE-754 a 4 byte, ad esempio, ha solo circa 7,5 cifre significative di precisione. Un tipo IEEE-754 a otto byte ha circa il doppio del numero di cifre significative. Apparentemente, il tipo reale di delphi ha una precisione che si trova intorno a 11 cifre significative. Il risultato di ciò è che qualsiasi cifra aggiuntiva di formattazione specificata potrebbe essere un rumore che può provocare conversioni tra valori formattati in base 10 e valori in virgola mobile in base 2.

Prima di tutto proverei a vedere se potevo ottenere aiuto dall'uso di Str con argomenti diversi o dall'aumento della precisione dei tipi nella tua app. (Hai provato a utilizzare Extended?)

Come ultima risorsa, ( Attenzione! Soluzione !! ) Proverei a salvare la rappresentazione di stringa del cliente insieme alla rappresentazione binaria in un elenco ordinato. Prima di riscrivere un valore in virgola mobile vedrei se esiste già un valore corrispondente nella tabella, la cui rappresentazione di stringa è già nota e può essere utilizzata al suo posto. Per rendere rapida questa ricerca, puoi ordinarla in base al valore numerico e utilizzare la ricerca binaria per trovare la corrispondenza migliore.

A seconda della quantità di elaborazione che è necessario eseguire, un'alternativa potrebbe essere quella di mantenere i numeri in formato BCD per conservare l'accuratezza originale.

È difficile rispondere a questa domanda senza sapere di che tipo sono ExportRealValue e ImportRealValue. Come altri hanno già detto, i tipi reali hanno tutti precisioni diverse.

Vale la pena notare che, contrariamente a quanto si pensa, l'estensione non è sempre maggiore precisione. Esteso è 10-20 cifre significative dove il doppio è 15-16. Dato che hai problemi con il decimo segno, forse stai già utilizzando l'estensione.

Per ottenere un maggiore controllo sulla lettura e la scrittura, puoi convertire i numeri da e verso le stringhe e scriverli in un flusso di file. Almeno in questo modo non devi preoccuparti se readln e writeln non ti fanno bene alle spalle.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top