Question

L’application de mon client exporte et importe un certain nombre de variables de type real via un fichier texte à l’aide de write et de readln. J'ai essayé d'augmenter la largeur des champs écrits pour que le code ressemble à:

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

Lorsque j'exporte, puis que je réimporte et réexporte, et que je compare les fichiers, la différence entre les deux derniers chiffres, p. ex.

-1.23456789012E-0002
-1.23456789034E-0002

Cela fait une différence dans l'application, le client veut savoir ce que je peux faire à ce sujet. Maintenant, je ne suis pas sûr que ce soit uniquement l'écriture / la lecture qui le fasse, mais j'ai pensé poser une question rapide avant de replonger dans la pile de disques. Est-ce que je dois aller en binaire?

Ce n'est pas une application traitant de la monnaie ou de quelque chose, je viens d'écrire et de lire les valeurs dans / à partir d'un fichier. Je sais que les points flottants sont parfois un peu étranges et je pensais que l’une des routines (Writeln / readln) pouvait avoir des activités amusantes.

Était-ce utile?

La solution

Si vous souhaitez spécifier la précision d'un réel avec un WriteLn, utilisez les éléments suivants:

WriteLn(RealVar:12:3);

Il affiche la valeur Realvar avec au moins 12 positions et une précision de 3.

Autres conseils

Vous pouvez essayer de passer à étendu pour une plus grande précision. Comme il a été souligné cependant, les nombres à virgule flottante n'ont qu'un nombre limité de chiffres significatifs en précision. Il est donc toujours possible d'afficher plus de chiffres, puis de les enregistrer avec précision, ce qui pourrait entraîner le comportement que vous avez spécifié.

Dans l'aide de Delphi:

Types réels Win32 fondamentaux

                                            | 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   
  

Remarque : le type Real48 à six octets a été appelé Real dans les versions antérieures d'Object Pascal. Si vous recompilez du code qui utilise l'ancien type Real à six octets dans Delphi, vous souhaiterez peut-être le modifier en Real48 . Vous pouvez également utiliser la directive du compilateur {$ REALCOMPATIBILITY ON} pour rétablir Réel dans le type à six octets. Les remarques suivantes s'appliquent aux types réels fondamentaux.

     
      
  • Real48 est conservé pour des raisons de compatibilité ascendante. Étant donné que son format de stockage n’est pas natif de l’architecture du processeur Intel, les performances sont plus faibles que celles des autres types à virgule flottante.
  •   
  • Étendu offre une plus grande précision que d'autres types réels, mais est moins portable. Soyez prudent avec Extended si vous créez des fichiers de données à partager sur plusieurs plates-formes.
  •   

Notez que la plage est supérieure aux chiffres significatifs. Donc, vous pouvez avoir un nombre plus grand que peut être stocké avec précision. Je recommanderais d'arrondir les chiffres significatifs pour éviter que cela ne se produise.

Lorsque vous utilisez des types à virgule flottante, vous devez être conscient des limitations de précision des types spécifiés. Un type IEEE-754 à 4 octets, par exemple, n'a qu'une précision d'environ 7,5 chiffres significatifs. Un type IEEE-754 à huit octets contient à peu près le double du nombre de chiffres significatifs. Apparemment, le type réel de Delphi a une précision d'environ 11 chiffres significatifs. Il en résulte que les chiffres supplémentaires de formatage spécifiés sont susceptibles de constituer du bruit pouvant entraîner des conversions entre les valeurs formatées en base 10 et les valeurs à virgule flottante en base 2.

Tout d'abord, j'essaierais de voir si je pouvais obtenir de l'aide en utilisant Str avec des arguments différents ou en augmentant la précision des types dans votre application. (Avez-vous essayé d'utiliser Extended?)

En dernier recours, ( Avertissement! Solution de contournement !! ), j'essaierais de sauvegarder la représentation sous forme de chaîne du client avec la représentation binaire dans une liste triée. Avant d'écrire une valeur en virgule flottante, je verrais s'il existe déjà une valeur correspondante dans la table, dont la représentation sous forme de chaîne est déjà connue et peut être utilisée à la place. Afin de rendre cette recherche rapide, vous pouvez la trier sur la valeur numérique et utiliser la recherche binaire pour trouver la meilleure correspondance.

En fonction du traitement que vous devez effectuer, vous pouvez également conserver les nombres au format BCD pour conserver la précision d'origine.

Il est difficile de répondre à cette question sans connaître le type de votre type ExportRealValue et ImportRealValue. Comme d'autres l'ont mentionné, les types réels ont tous des précisions différentes.

Il vaut la peine de noter que contrairement à certaines idées reçues, l’extension n’est pas toujours plus précise. Extended est 10-20 chiffres significatifs où double est 15-16. Alors que vous avez des problèmes autour du dixième signe, vous utilisez peut-être déjà étendu.

Pour mieux contrôler la lecture et l'écriture, vous pouvez convertir vous-même les nombres en chaînes et les écrire dans un flux de fichiers. Au moins, vous ne devez pas vous inquiéter si readln et write ne font rien de bon derrière le dos.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top