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 Delphi Discussion :

roundto simperoundto currency arrondi incorrect


Sujet :

Langage Delphi

  1. #1
    Membre expérimenté
    Avatar de ouiouioui
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2006
    Messages
    984
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2006
    Messages : 984
    Points : 1 419
    Points
    1 419
    Par défaut roundto simperoundto currency arrondi incorrect
    Bonjour, comment avoir un arrondi de banque correct à chaque fois ?
    avec 6,545 roundto me donne 6.54

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var 
      TaxeTotal: currency;
    begin
      TaxeTotal := 6.545;
      TaxeTotal := RoundTo(TaxeTotal, -2);//donne 6.54
    si je met
    SetRoundMode(rmNearest);
    avant, sa change rien.

    selon l'aide et la logique je devrait et veux avoir 6.55

    sa fait 2 jours que je cherche, je devient chèvre.

    j'ai trouvé des posts qui parle de ce problème et liste des test avec d'autres fonctions mais pas de soution.

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 586
    Points : 25 262
    Points
    25 262
    Par défaut
    On a parlé de ça : Round : arrondir à l'entier supérieur quand on est à 0,5 ?

    Sinon Currency, pense que c'est un FAUX flottant, en fait c'est un Int64 avec 4 chiffres après la virgule !
    L'affecter à RoundTo peut provoquer une erreur d'arrondi, genre "6.545" devient "6.54499999999"

    rmNearest est le mode par défaut !

    As-tu essayé SimpleRoundTo au lieu de RoundTo ?
    Cela fait débat : Arrondi classique vs Arrondi bancaire

    RoundTo Extrait de l'aide :
    arrondir la valeur qui se trouve exactement au milieu des deux valeurs ...
    Cette méthode arrondit à un nombre pair dans le cas où AValue n'est pas plus proche d'une des deux valeurs.
    ? C'est étrange cet arrondi à un nombre pair non ?
    Pour moi, la parité c'est que sur des nombres entiers, je pige pas bien !

    du coup, 6.54 est-ce considéré comme pair ?
    et donc 6.55 est-ce considéré comme impair ?
    donc jamais ça sera 6.55 en mode rmNearest
    rmUp peut être une solution mais risque de changer l'arrondi de 6.544

    En C++Builder, j'ai testé en rmNearest
    6.225 : Round 6,22 | Simple 6,22 != 6,23 - NOK ? Pair !
    6.235 : Round 6,24 | Simple 6,24 - OK
    6.245 : Round 6,25 | Simple 6,25 - OK
    6.255 : Round 6,25 | Simple 6,25 != 6,26 - NOK ? Impair ???
    6.265 : Round 6,26 | Simple 6,26 != 6,27 - NOK ? Pair !

    6.525 : Round 6,53 | Simple 6,53 - OK
    6.535 : Round 6,54 | Simple 6,54 - OK
    6.545 : Round 6,54 | Simple 6,54 != 6,55 - NOK ? Pair !
    6.555 : Round 6,55 | Simple 6,55 != 6,56 - NOK ? Impair ???
    6.565 : Round 6,57 | Simple 6,57 - OK
    Si quelqu'un pige ?
    Suis-je mauvais en arrondi ?
    Pour moi, si 0 à 4, j'arrondi par le bas, si 5 à 9, j'arrondis par le haut

    6.54499999999 sur -3 : Round 6,5450 | Simple 6,5450
    6.54499999999 sur -2 : Round 6,5400 | Simple 6,5400
    6.54499999999 sur -1 : Round 6,5000 | Simple 6,5000
    6.54499999999 sur +0 : Round 7,0000 | Simple 7,0000
    Au moins sur 0.5 vers un entier, c'est cohérent avec l'histoire des Pair pour Round et Simple fait ce que j'aurais fait !
    0.5 : Round 0,00 | Simple 1,00
    1.5 : Round 2,00 | Simple 2,00
    2.5 : Round 2,00 | Simple 3,00
    3.5 : Round 4,00 | Simple 4,00
    4.5 : Round 4,00 | Simple 5,00

  3. #3
    Membre confirmé
    Homme Profil pro
    Santé
    Inscrit en
    Septembre 2010
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Santé
    Secteur : Santé

    Informations forums :
    Inscription : Septembre 2010
    Messages : 290
    Points : 534
    Points
    534
    Par défaut Avantage de l'arrondi bancaire:
    Citation Envoyé par ShaiLeTroll Voir le message
    ? C'est étrange cet arrondi à un nombre pair non ?
    Si on arrondit à chaque fois par excès les nombres dont le dernier chiffre est cinq, on finit par cumuler une erreur par excès...

    En prenant le chiffre pair, tantôt c'est une erreur par exès, tantôt par défaut. Sur de nombreuses opérations, ce sera statistiquement plus exact.

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 586
    Points : 25 262
    Points
    25 262
    Par défaut
    Ah, c'est pour que la moyenne des arrondis soient plus proche du la somme réelle !
    C'est pas con mais ça dépend du métier, si l'on a pas envie de se prendre la tête cela se comprend mieux !
    Merci pour l'info !

    Perso, je n'arrondi jamais mes valeurs en DB, je laisse le maximum issu de la source (manuelle, appareil de labo, de mesure ...)
    Déjà, en fait, les flottants, j'en ai très rarement !
    C'est souvent l'affichage qui va le gérer, et comme il y a rarement de cumul comme en compta où l'on a toujours ce centime à la comme dans les comptes

    En compta, il y a un compte qui conservent l'arrondi comme 658 et 758 pour que les journaux soient justement équilibrés !


    Donc que RoundTo fasse son équilibre pourquoi pas !
    Mais pourquoi SimpleRoundTo lui qui devrait selon la doc AValue se situe exactement au milieu des deux valeurs les plus proches ayant la puissance de dix spécifiée (au-dessus et en dessous), cette fonction renvoie : La valeur vers plus l'infini si AValue est positif.

    Ne devrait pas donner la même chose que RoundTo ?
    On a choisi SimpleRoundTo pour son arrondi à l'excès pourquoi ne le fait-il pas ?

    6.215 : Round 6,2100 | Simple 6,2100
    6.225 : Round 6,2200 | Simple 6,2200
    6.235 : Round 6,2400 | Simple 6,2400
    6.245 : Round 6,2500 | Simple 6,2500
    6.255 : Round 6,2500 | Simple 6,2500
    6.265 : Round 6,2600 | Simple 6,2600
    6.275 : Round 6,2800 | Simple 6,2800

    6.515 : Round 6,5100 | Simple 6,5100
    6.525 : Round 6,5300 | Simple 6,5300
    6.535 : Round 6,5400 | Simple 6,5400
    6.545 : Round 6,5400 | Simple 6,5400
    6.555 : Round 6,5500 | Simple 6,5500
    6.565 : Round 6,5700 | Simple 6,5700
    6.575 : Round 6,5800 | Simple 6,5800
    Comment prédire le résultat ?
    SimpleRoundTo ne fait pas en C++Builder XE2 un arrondi vers l'infini à cause des arrondis foireux !

    Si l'on prend le calcul de SimpleRoundTo (dispo dans Sytem.Math.pas vers L960)
    J'ai décomposé le code de SimpleRoundTo étape par étape en C++Builder

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
      Extended LFactor35 = 0.01;
      Extended AValue35 = 6.535;
      Extended Powered35 = AValue35 / LFactor35;
      Extended Adjusted35 = Powered35 + 0.5;
      Extended Truncated35 = Int(Adjusted35);
      Extended Result35 = Truncated35 * LFactor35;
      MemoTrace->Lines->Add(Format("%.4f : Powered %.4f | Adjusted %.4f | Truncated %.4f | Result %.4f ", OpenArray<TVarRec>(AValue35, Powered35, Adjusted35, Truncated35, Result35), 5));
     
      Extended LFactor45 = 0.01;
      Extended AValue45 = 6.545;
      Extended Powered45 = AValue45 / LFactor45;
      Extended Adjusted45 = Powered45 + 0.5;
      Extended Truncated45 = Int(Adjusted45); // Oui c'est bien 655 -> 654 !!!
      Extended Result45 = Truncated45 * LFactor45;
      MemoTrace->Lines->Add(Format("%.4f : Powered %.4f | Adjusted %.4f | Truncated %.4f | Result %.4f ", OpenArray<TVarRec>(AValue45, Powered45, Adjusted45, Truncated45, Result45), 5));
     
      Extended PoweredM = 6.545 / 0.01;
      Extended AdjustedM = PoweredM + 0.5;
      Extended TruncatedM = Int(AdjustedM);
      MemoTrace->Lines->Add(Format("Powered %.4f | Adjusted %.4f | Truncated %.4f", OpenArray<TVarRec>(PoweredM, AdjustedM, TruncatedM), 3));

    Format %.4f
    6,5350 : Powered 653,5000 | Adjusted 654,0000 | Truncated 654,0000 | Result 6,5400
    6,5450 : Powered 654,5000 | Adjusted 655,0000 | Truncated 654,0000 | Result 6,5400
    Powered 654,5000 | Adjusted 655,0000 | Truncated 655,0000
    Format %.15f
    6,535000000000000 :
    Powered 653,500000000000001 |
    Adjusted 654,000000000000001 |
    Truncated 654,000000000000000 |
    Result 6,540000000000000

    6,545000000000000 :
    Powered 654,499999999999979 |
    Adjusted 654,999999999999979 |
    Truncated 654,000000000000000 |
    Result 6,540000000000000

    Powered 654,500000000000000 |
    Adjusted 655,000000000000000 |
    Truncated 655,000000000000000
    ça pue !

    Le SimpleRoundTo est tout simplement buggé pour certaines valeurs parce que le format floattant n'est pas très précis
    Cela malheureusement est un problème fréquent d'où l'importance de ne jamais stocker de valeur tronquée !

    Au début, je pensais utiliser un Epsilon comme dans CompareValue mais il faut gérer l'erreur vers le haut et vers le bas, cela ne fonctionne pas !

    Du coup, on peut tricher,
    On commence par arrondir son nombre sur 2 digit supplémentaire, cela retire les approximation du format floattant sans trop perturbé l'arrondi (sauf dans les cas x.4999)
    A partir de ce nouveau nombre, on arrondi sur le réel nombre de digit souhaité :

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //---------------------------------------------------------------------------
    Extended SimpleRoundToE(const Extended AValue, const TRoundToRange ADigit = -2)
    {
      if (ADigit < 0)
        return SimpleRoundTo(SimpleRoundTo(AValue, ADigit - 2), ADigit);
      else
        return SimpleRoundTo(AValue, ADigit);
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //---------------------------------------------------------------------------
    procedure SimpleRoundToE(const AValue: Extended; const ADigit: TRoundToRange = -2): Extended;
    begin
      if ADigit < 0 then
        Result = SimpleRoundTo(SimpleRoundTo(AValue, ADigit - 2), ADigit)
      else
        Result = SimpleRoundTo(AValue, ADigit);
    end;
    ou encore spécifique au Currency
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Currency SimpleRoundToCurrency(const Currency AValue, const TRoundToRange ADigit = -2)
    {
      Currency Result;
      Extended RawValue = AValue.Val;
      Result.Val = _roundToInt64(SimpleRoundTo(RawValue, 4 + ADigit));
      return Result;
    }


    Cela fonctionne nettement mieux pour les valeurs en x.xx5 mais cela doit provoquer surement d'autres erreurs (peut-être plus difficile à trouver genre x.44999... ou x.50001...)
    0.5 : Round 0,0000 | Simple 1,0000 | Epsilon 1,0000
    1.5 : Round 2,0000 | Simple 2,0000 | Epsilon 2,0000
    2.5 : Round 2,0000 | Simple 2,0000 | Epsilon 3,0000
    3.5 : Round 4,0000 | Simple 4,0000 | Epsilon 4,0000
    4.5 : Round 4,0000 | Simple 5,0000 | Epsilon 5,0000
    0.05 : Round 0,0000 | Simple 0,0000 | Epsilon 0,0000
    0.05 : Round 0,1000 | Simple 0,1000 | Epsilon 0,1000
    1.05 : Round 1,0000 | Simple 1,0000 | Epsilon 1,0000
    1.05 : Round 1,1000 | Simple 1,1000 | Epsilon 1,0000

    1.235 : Round 1,2400 | Simple 1,2400 | Epsilon 1,2400
    1.245 : Round 1,2500 | Simple 1,2500 | Epsilon 1,2500

    6.215 : Round 6,2100 | Simple 6,2100 | Epsilon 6,2200
    6.225 : Round 6,2200 | Simple 6,2200 | Epsilon 6,2300
    6.235 : Round 6,2400 | Simple 6,2400 | Epsilon 6,2400
    6.245 : Round 6,2500 | Simple 6,2500 | Epsilon 6,2500
    6.255 : Round 6,2500 | Simple 6,2500 | Epsilon 6,2600
    6.265 : Round 6,2600 | Simple 6,2600 | Epsilon 6,2700
    6.275 : Round 6,2800 | Simple 6,2800 | Epsilon 6,2800

    6.515 : Round 6,5100 | Simple 6,5100 | Epsilon 6,5200
    6.525 : Round 6,5300 | Simple 6,5300 | Epsilon 6,5300
    6.535 : Round 6,5400 | Simple 6,5400 | Epsilon 6,5400
    6.545 : Round 6,5400 | Simple 6,5400 | Epsilon 6,5500
    6.555 : Round 6,5500 | Simple 6,5500 | Epsilon 6,5600
    6.565 : Round 6,5700 | Simple 6,5700 | Epsilon 6,5700
    6.575 : Round 6,5800 | Simple 6,5800 | Epsilon 6,5800

    6.214 : Round 6,2100 | Simple 6,2100 | Epsilon 6,2100
    6.224 : Round 6,2200 | Simple 6,2200 | Epsilon 6,2200
    6.234 : Round 6,2400 | Simple 6,2300 | Epsilon 6,2300
    6.244 : Round 6,2500 | Simple 6,2400 | Epsilon 6,2400
    6.254 : Round 6,2500 | Simple 6,2500 | Epsilon 6,2500
    6.264 : Round 6,2600 | Simple 6,2600 | Epsilon 6,2600
    6.274 : Round 6,2800 | Simple 6,2700 | Epsilon 6,2700

    6.219 : Round 6,2100 | Simple 6,2200 | Epsilon 6,2200
    6.229 : Round 6,2200 | Simple 6,2300 | Epsilon 6,2300
    6.239 : Round 6,2400 | Simple 6,2400 | Epsilon 6,2400
    6.249 : Round 6,2500 | Simple 6,2500 | Epsilon 6,2500
    6.259 : Round 6,2500 | Simple 6,2600 | Epsilon 6,2600
    6.269 : Round 6,2600 | Simple 6,2700 | Epsilon 6,2700
    6.279 : Round 6,2800 | Simple 6,2800 | Epsilon 6,2800

    6.419 : Round 6,4000 | Simple 6,4000 | Epsilon 6,4000
    6.429 : Round 6,4000 | Simple 6,4000 | Epsilon 6,4000
    6.439 : Round 6,4000 | Simple 6,4000 | Epsilon 6,4000
    6.449 : Round 6,4000 | Simple 6,4000 | Epsilon 6,4000
    6.459 : Round 6,5000 | Simple 6,5000 | Epsilon 6,5000
    6.469 : Round 6,5000 | Simple 6,5000 | Epsilon 6,5000
    6.479 : Round 6,5000 | Simple 6,5000 | Epsilon 6,5000
    6,535000000000000 : Powered 653,500000000000001 | Adjusted 654,000000000000001 | Truncated 654,000000000000000 | Result 6,540000000000000
    6,545000000000000 : Powered 654,499999999999979 | Adjusted 654,999999999999979 | Truncated 654,000000000000000 | Result 6,540000000000000
    Powered 654,500000000000000 | Adjusted 655,000000000000000 | Truncated 655,000000000000000

    6.54499999999 sur -3 : Round 6,5450 | Simple 6,5450 | Epsilon 6,5450
    6.54499999999 sur -2 : Round 6,5400 | Simple 6,5400 | Epsilon 6,5500
    6.54499999999 sur -1 : Round 6,5000 | Simple 6,5000 | Epsilon 6,5000
    6.54499999999 sur +0 : Round 7,0000 | Simple 7,0000 | Epsilon 7,0000

  5. #5
    Membre expérimenté
    Avatar de ouiouioui
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2006
    Messages
    984
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2006
    Messages : 984
    Points : 1 419
    Points
    1 419
    Par défaut
    tu dis que tu gardes les valeurs non arrondies dans la base de données, moi cela me pose un problème car j'utilise des composants tierce comme par exemple faste report pour l'impression du coup si je n'arrondis pas les valeurs, je n'ai pas étudié les rapports je ne connais pas la méthode qui est utilisée pour arrondir mais en tout cas mon résultat affiché et le résultat imprimé peut varier ce qui est forcément problématique.

    À plusieurs endroits il recommande d'utiliser d'autres fonctions comme par exemple http://cc.embarcadero.com/item.aspx?id=21909

    il y a des rapports d'erreur mais quand on lis les commentaires sa n'a pas vraiment l'air résolu
    http://qc.embarcadero.com/wc/qcmain.aspx?d=8143
    http://qc.embarcadero.com/wc/qcmain.aspx?d=8070

    en fait ya pas de soluce, j'utilise simpleroundto.

    Merci à tous.

  6. #6
    Membre confirmé
    Homme Profil pro
    Santé
    Inscrit en
    Septembre 2010
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Santé
    Secteur : Santé

    Informations forums :
    Inscription : Septembre 2010
    Messages : 290
    Points : 534
    Points
    534
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    ça pue !
    Vouloir arrondir des approximations c'est chercher les emm...

    De toute façon les calculs en virgule flottante n'ont jamais embaumé la vie des programmeurs.


    Et ça? Ca pue pas?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      var A,B: Double; { Double précision conseillé car plus portable que le type Extended (je me marre doucement). }
      begin
        A := Power(2,60)+1;
        B := Power(2,60)  ;
        Edit1.Text := FloattoStr(A-B); // -> 0 !!!  
      end;
    Et y'en a d'autres.. mais j'suis pas prof de puanteur.


    PS: TaxeTotal := (Trunc(TaxeTotal*100+0.5))/100;

  7. #7
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 586
    Points : 25 262
    Points
    25 262
    Par défaut
    Citation Envoyé par Caribensila Voir le message
    Vouloir arrondir des approximations c'est chercher les emm...
    Ben, vu que tout le sujet est parti d'une valeur théorique de 6,545 mais qui en réalité est 654,499999999999979 ...
    Je me suis dit que c'est typiquement la valeur qui fera foiré le code qui fonctionne pour le reste !
    En général, j'ai cherché la petite bête !

    Je trouve que la Documentation de SimpleRoundTo devrait contenir un petit avertissement que même en Extended (la soit disant "très haute précision"), les nombres réels n'étant que des approximations, l'arrondi d'une valeur au milieu des deux valeurs les plus proches sera affecté par ce phénomène !


    Même Hint du débogueur n'affiche pas la valeur approximative
    mais la valeur que l'on croit avoir parce qu'il arrondi pour l'affichage à peut-être à 10 ou 15-16 digit (pile poil AVANT le 7)

    Seul un Format en 15f m'a fait voir l'anomalie d'approximation !

    Citation Envoyé par Caribensila Voir le message
    De toute façon les calculs en virgule flottante n'ont jamais embaumé la vie des programmeurs.
    C'est vrai !
    Je ne pratique quasiment jamais, je crois que mes derniers double (pour un projet professionnel) c'était en 2009 !
    Et encore, les valeurs étaient fournis par des appareils déjà arrondis à 3 digit, je ne faisais que les stocker et quelques calculs de seuil (évidemment, j'utilisais CompareValue en Epsilon 0.001)

    j'arrondi encore moins souvent !
    la plupart du temps c'est la définition du champ de la DB qui déterminera le nombre de digit stocké puis j'utilise Format() ou DisplayFormat au besoin pour l'affichage



    Citation Envoyé par Caribensila Voir le message
    Double précision conseillé car plus portable que Extended
    ils ont résolu le problème en Win64 : tout en Double



    Citation Envoyé par Caribensila Voir le message
    Power(2,60)
    tu pousses aussi, 19 chiffres tu atteins effectivement la limite

    Extended
    Type Etendue positive approximative . . . . . . . . . Chiffres significatifs
    Plates-formes 32 bits : 3.4e-4932 .. 1.1e+4932 . . 10-20
    Plates-formes 64 bits : 5.0e-324 .. 1.7e+308 . . . 15-16
    Que veux dire 10-20 ?
    Cela veut-il dire que certains nombre n'auront que 10 digits, d'autre 20 et certains 15 ou même 12 ?
    En gros une précision variable ?

    Citation Envoyé par ouiouioui Voir le message
    tu dis que tu gardes les valeurs non arrondies dans la base de données .. le résultat imprimé peut varier ce qui est forcément problématique.
    Effectivement si l'arrondi de Fast Report est différent (trés peu probable) de l'arrondi de la fonction Format de Delphi, tu pourras avoir un écart dans entre l'affichage et l'impression !
    J'ai toujours utilisé des outils d'impression gérant le TField et DisplayFormat, du coup c'est Delphi qui le gère dans son GetText !

    Attention, c'est que mon code n’arrondit pas explicitement mais la DB elle le fait par exemple si j'ai défini un champ en DECIMAL(8,4) cela arrondira évidemment
    Disons, que je ne m'en préoccupe pas, on verra bien si un jour un client voit un pouième d'erreur !

  8. #8
    Membre confirmé
    Homme Profil pro
    Santé
    Inscrit en
    Septembre 2010
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Santé
    Secteur : Santé

    Informations forums :
    Inscription : Septembre 2010
    Messages : 290
    Points : 534
    Points
    534
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    tu pousses aussi, 19 chiffres tu atteins effectivement la limite
    Ben, dans la petite histoire suivante je pousse pas, là.

    Petite histoire de mon ami Kenavo :

    Soucieux d'assurer un certain confort à mes vieux jours, je suis allé trouver mon banquier. Comme je n'avais qu'un peu moins de deux euros en poche, il m'a proposé ce plan :
    "Vous déposez (e-1) euros soit 1.7182818651 €. La première année, vous y perdrez, car on multiplie votre avoir par 1 et on prélève 1.00 € de frais de gestion. Mais le deuxième année, on multiplie votre avoir par 2 et on prélève toujours 1.00 €. La troisième année, on multiplie par 3, et ainsi de suite, le n-ième année on multiplie par n, tout en ne prélevant chaque année qu'un euro. Ça vous va ? Signez là !
    - Hou, là ! M. le banquier ! Votre empressement me trouble. Cette offre ne cacherait-elle point quelque flouerie ? Je m'en vais de ce pas m'enquérir après de mon ordinateur de ce que pourrait cacher votre proposition, et calculer que deviendront dans 25 ans les précieuses économies que vous me demandez de vous confier! Je pratique Delphi, moi !"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    procedure TForm1.CalculeMaFortune;
    var
      x : real48;
    //  x : single;
    //  x : double;
    //  x : extended;
      i : integer;
    begin
      x := exp(1)-1;
      for i:=1 to 25 do
      begin
        x:=(x*i)-1;
      end;
      Edit1.Text :=FloatToStrf(x,ffFixed,25,2);
    end;
    si X est du type Real48, je devrais 13069463212960.00 € dans 25 ans,
    si X est du type Single, j'aurais 568654735142289408.00 € dans 25 ans,
    si X est du type Double, j'aurais 1201807247.41 € dans 25 ans,
    si X est du type Extended, j'aurais 1052910.85 € dans 25 ans.


    Au fait, la bonne réponse :
    0.039 938 729 673 230 208 903 671 455 210 361 060 981 080

  9. #9
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 586
    Points : 25 262
    Points
    25 262
    Par défaut
    Tu as un tel écart entre le vrai calcul et la version informatique !
    Ouch !
    Tout ça pour un petit arrondi par excès qui s'accumule

    Sur Calc
    (((((((((((((((((((((((((1,7182818651-1)*2-1)*3-1)*4-1)*5-1)*6-1)*7-1)*8-1)*9-1) *10-1)*11-1)*12-1)*13-1)*14-1)*15-1)*16-1)*17-1)*18-1)*19-1)*20-1)*21-1)*22-1)*23-1)*24-1)*25-1)
    -> 568345545542515852,7584

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [OpenOffice] [Code] Arrondi incorrect
    Par Laurente dans le forum OpenOffice & LibreOffice
    Réponses: 1
    Dernier message: 27/04/2008, 19h12
  2. [BigDecimal] les arrondis...
    Par LoulouFifi dans le forum API standards et tierces
    Réponses: 3
    Dernier message: 13/01/2004, 18h37
  3. création d'un bouton de forme arrondie
    Par THIERRY L. dans le forum C++Builder
    Réponses: 2
    Dernier message: 15/12/2003, 14h04
  4. [VB6] Racine carrée + arrondi
    Par Krys29 dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 28/10/2002, 13h19
  5. [VB6] [MSChart] Courbe incorrecte
    Par elifqaoui dans le forum VB 6 et antérieur
    Réponses: 18
    Dernier message: 08/10/2002, 21h53

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