IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Opérations arithmétiques sur du texte


Sujet :

Langage C++

  1. #1
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut Opérations arithmétiques sur du texte
    Salut,

    Je cherche un moyen simple et efficace de faire des opérations d'addition/soustraction sur des nombres décimaux représentés sous forme de texte.

    Par exemple "10.2" + "0.4" = "10.6"

    Merci

    Quelques explications pour le contexte de cette demande :

    Je manipule des données stockées au format texte que je représente en "double" et parfois je dois les comparer exactement entre elles. Le problème c'est que j'ai des effets de bord liés au fait que pour certains nombres l'égalité suivante est fausse atof("10.2") + atof("0.4") == atof("10.6").

    Il y a bien sûr la possibilité de faire le test à epsilon près mais il se trouve que ça alourdit énormément mes calculs de comparaison qui sont extrêmement nombreux, en revanche la quantité de nombres résultats d'une opération d'addition/soustraction est beaucoup plus restreinte. Donc je préfère garder un test exact et m'assurer que je manipule toujours des nombres exactement les mêmes que la conversion de leur équivalent texte.

  2. #2
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    A part en refaisant "à la main" les opérations sur les chaînes comme on le fait sur papier (=> en gros, créer une classe dont la chaîne est l'attribut, et surcharger les opérateurs), je ne vois pas.

    Ceci étant dit, ça ne va pas forcément être simple, même si ce n'est pas non plus très compliqué.

    J'explique : il faut trouver la position du séparateur décimal, donc le "." (attention aux conventions locales si jamais tu y es soumis).
    Ensuite, il faut normaliser la chaîne, avec par exemple systématiquement 10 chiffres après la virgule, et 10 chiffres devant. Ainsi, chaque nombre sera stocké sur un nombre constant de caractères, avec la virgule toujours au même endroit.
    Ensuite, pour l'addition par exemple : tu pars du dernier caractère pour les deux termes, tu additionnes en ENTIERS (=> exact), tu propages la retenue sur l'opération de gauche et tu continues jusqu'à avoir fait chaque rang.

    Après, ça marche, et ça sera sans aucune perte de précision... Par contre, j'ai bien peur que ça ne te coûte horriblement cher côté temps CPU et place mémoire !!

    Après, si tu es ouvert aux suggestions, je te conseillerais de t'orienter vers des nombres en virgule fixe, qui garderont la précision dont tu as besoin. Tu peux trouver une librairie ici, par exemple, mais il en existe sûrement beaucoup d'autres.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  3. #3
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut
    Merci,

    L'idée des nombres à virgule fixe semble intéressante. Par contre je ne vois pas par quel biais je peux être sûr qu'on a toujours :

    Si aa.a + bb.b = cc.c alors
    Fixed(atof("aa.a")) = Fixed(atof("bb.b")) + Fixed(cc.c)

  4. #4
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut
    En fait je viens de penser à une autre possibilité dont je n'ai pas encore la solution :

    Il me suffit étant donné un nombre dont j'ai la représentation en virgule flottante de trouver le nombre à virgule flottante le plus proche qui soit une conversion d'un nombre sous forme texte avec un nombre maximum connu de chiffres après la virgule.

    Ainsi je fais tranquillement mes opération sur les flottants et le résultat je l'arrondis au plus proche flottant qui représente une conversion "valide".

  5. #5
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Heu, non, tu as fait une confusion : en virgule fixe, tu passes directement de la chaîne au nombre en VF, SANS PASSER PAR DES FLOTTANTS. Sinon, tu en perds tout le bénéfice !!
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  6. #6
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Heu, non, tu as fait une confusion : en virgule fixe, tu passes directement de la chaîne au nombre en VF, SANS PASSER PAR DES FLOTTANTS. Sinon, tu en perds tout le bénéfice !!
    Ah ben ça c'est problématique car j'ai quand même besoin de faire des calculs avec la précision des flottants...

    Je crois que je vais continuer dans mon idée d'arrondir au plus proche flottant valide.

  7. #7
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Pourquoi faire ??? Les calculs en virgule fixe sont, en général, plus précis que ceux en virgule flottante (du moins, si on paramètre la librairie VF pour utiliser suffisamment de chiffres)... Cela s'utilise comme des flottants, via les surcharges d'opérateur, donc c'est "invisible" côté code source.
    Tu n'as à utiliser les flottants (via une conversion) QUE si tu dois explicitement passer un "float", "double" ou "long double" à un module tiers. Et tu le fais en FIN de calcul, bien sûr, afin de conserver un maximum de précision.

    Côté inconvénients : les calculs en VF sont en général plus longs qu'en FP (les copros mathématiques sont très performants, quand même), et un nombre en VF est souvent plus gros que le FP correspondant. C'est la raison pour laquelle ce genre de truc n'est plus trop utilisé en dehors des domaines où les erreurs d'arrondi sont inacceptables.
    Historiquement, on s'en servait aussi il y a quelques années pour accélérer les calculs, quand les FPU n'étaient pas considérés comme allant de soi sur chaque machine.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  8. #8
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Les calculs en virgule fixe sont, en général, plus précis que ceux en virgule flottante
    - les calculs en virgule fixe sont faits a erreur absolue constante, ceux en virgule flottante sont une assez bonne approximation de l'erreur relative constante.

    - pour les flottants comme pour les nombres en virgule fixe, un facteur important est la base choisie. Malgre les efforts d'IBM, les implementations hard comme soft des flottants sont generalement binaires. Il y a plus de variation dans le cas des nombres en virgule fixe: l'utilisation d'une base decimale est courante. Quand, comme dans le cas present, les donnees proviennent d'un source textuelle en decimal, la conversion de celle-ci dans le format (flottant ou fixe) introduit une erreur si la cible est binaire (on ne peut pas representer exactement 1./5 en binaire pas plus qu'on ne peut representer exactement 1/3 en decimal, ce n'est pas une question de precision mais de quantification).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  9. #9
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    - les calculs en virgule fixe sont faits a erreur absolue constante, ceux en virgule flottante sont une assez bonne approximation de l'erreur relative constante.
    La précision en virgule fixe est paramétrable, contrairement à celle des flottants... Si je veux effectuer des calculs en VF à une précision de 10^(-100), je le peux, même si ce sera bien sûr très coûteux en temps et sûrement coûteux en mémoire aussi.
    En FP, additionner un milliard à un milliardième suffit souvent pour tout faire partir en sucette côté arrondis...

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    (on ne peut pas representer exactement 1./5 en binaire pas plus qu'on ne peut representer exactement 1/3 en decimal, ce n'est pas une question de precision mais de quantification).
    Ses chiffres sont d'ores et déjà décimaux, donc finis, et il n'utilise que les opérations d'addition/soustraction (donc pas de division produisant un irrationnel).
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  10. #10
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Ses chiffres sont d'ores et déjà décimaux, donc finis, et il n'utilise que les opérations d'addition/soustraction (donc pas de division produisant un irrationnel).
    Finis en base décimale, pas finis en base binaire...
    http://babbage.cs.qc.edu/IEEE-754/Decimal.html
    tapes 1.2 et convertis.

  11. #11
    screetch
    Invité(e)
    Par défaut
    pour tnarol : pour résoudre ton probleme il te faudrait une lib de calculs en flottant dont tu puisses changer la base. La précision doit etre au moins égale a la plus grande chaine que tu peux entrer, +1
    (si tu veux calculer 9 + 9, chaque nombre contient 1 chiffre, la précision nécessaire pour calculer le résultat est 1+max(1,1) soit 2, effectivement 18 tiens sur deux chiffres). si tu connais le format de tes chaines c'est alors tres facile de savoir quelle précision il te faut.

  12. #12
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par screetch Voir le message
    Finis en base décimale, pas finis en base binaire...
    http://babbage.cs.qc.edu/IEEE-754/Decimal.html
    tapes 1.2 et convertis.
    T'es en flottant, là, pas en virgule fixe...

    En VF, ça donnerait plutôt un truc du genre "0x00, 0x01, 0x02, 0x00" avec la virgule fixe au milieu des 32 bits. Une opération en virgule fixe, c'est "simplement" une opération sur des ENTIERS avec une prise en compte artificielle de la position de la virgule.
    Donc, pas d'erreurs d'arrondis, pas d'erreurs de précision (sauf celle fixée par la décision d'utiliser N chiffres avant/après la virgule bien sûr), et on peut même implémenter des nombres rationnels (dans Q) très simplement.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  13. #13
    screetch
    Invité(e)
    Par défaut
    t'es chiant de changer a chaque fosi de référentiel pour avoir raison, oui en virgule fixe ca peut marcher, mais ce n'est pas la solution du probleme, la virgule flottante n'est pas non plus l'origine du probleme, c'est la base de l'opération.

    c'est chiant de se voir rembarrer a chaque fois parce que tu changes le référentiel du probleme pour s'adapter a ta solution......

  14. #14
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    En VF, ça donnerait plutôt un truc du genre "0x00, 0x01, 0x02, 0x00" avec la virgule fixe au milieu des 32 bits. Une opération en virgule fixe, c'est "simplement" une opération sur des ENTIERS avec une prise en compte artificielle de la position de la virgule.
    Donc, pas d'erreurs d'arrondis, pas d'erreurs de précision (sauf celle fixée par la décision d'utiliser N chiffres avant/après la virgule bien sûr), et on peut même implémenter des nombres rationnels (dans Q) très simplement.
    Ben non.
    • En virgule fixe binaire, quel que soit le nombre de bits, tu ne pourras jamais représenter exactement 1.3. Sinon, ce n'est plus de la virgule fixe binaire, mais autre chose (ton exemple me fait penser à du BCD non-compact).
    • En virgule fixe décimale, pas de problème: On choisit le nombre de chiffres après la virgule et on multiplie la valeur par 10^chiffres.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  15. #15

  16. #16
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    (ton exemple me fait penser à du BCD non-compact)
    Parce que ce sont des chiffres simples.

    Prenons un exemple plus parlant : "524.4322". Cela donnerait (précision 10^9 / 10^-9) "0x0000020C.10E20000" (j'ai introduit le "." pour montrer la position de la virgule fixe).
    Deux nombres 32 bits, entiers, stockant donc un chiffre en VF en précision 10^(+/-)9 suivant dans quel sens on part. Et aucun problème pour représenter 1.3, bien sûr, vu que c'est un nombre fini dans les limites de la précision supportée.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  17. #17
    screetch
    Invité(e)
    Par défaut
    0x0000020C.000010E2

  18. #18
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Je pense que ça donnerait plutôt 0x0000020C.19C2D940, ou bien même une addition serait PITA à effectuer (on serait obligé de normaliser).

    Évidemment, ce n'est pas la notion que j'ai de "virgule fixe", vu que cette représentation laisse un "trou" dans l'espace binaire utilisé. Mais ça doit quand même être compatible avec ce terme...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  19. #19
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par screetch Voir le message
    0x0000020C.000010E2
    Oups... Mais ni l'un ni l'autre, en fait, j'ai oublié d'étendre le domaine avant la conversion.

    524.4322 = 000 000 524 . 432 200 000 = 0000 020C . 19C2 D940

    EDIT : Grilled...
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  20. #20
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Évidemment, ce n'est pas la notion que j'ai de "virgule fixe", vu que cette représentation laisse un "trou" dans l'espace binaire utilisé. Mais ça doit quand même être compatible avec ce terme...
    En effet, il y a un léger reliquat qui sert aux arrondis (lorsque l'on utilise des divisions notamment).
    Pour ma part, c'est ainsi que j'ai toujours vu les virgules fixes, mais je dois dire que j'ai connu ce principe à l'époque du DOS aussi... Donc, le but était une conversion ultra rapide et des calculs portant quasi-exclusivement sur des entiers. Et oui, une normalisation était requise.

    Pour l'anecdote, les sinus / cosinus étaient précalculés via des tables, à partir d'un cercle divisé en 256 ou 512 parties (afin de pouvoir effectuer les tours via un simple masque binaire), et beaucoup d'opérations "complexes" (logarithmes, racines, etc.) étaient faites via des développement limités.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

Discussions similaires

  1. Opérations arithmétiques sur les Listes
    Par yoshik dans le forum Général Python
    Réponses: 33
    Dernier message: 17/06/2009, 18h39
  2. Réponses: 3
    Dernier message: 29/03/2009, 22h40
  3. Opérations arithmétiques sur les caractères
    Par JolyLoic dans le forum C
    Réponses: 6
    Dernier message: 18/01/2009, 21h59
  4. Opérations arithmétiques sur matrices creuses
    Par fdl1508 dans le forum Pascal
    Réponses: 3
    Dernier message: 25/12/2007, 12h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo