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 :

Tableau - résultats inadéquats d'arrondis


Sujet :

Langage Delphi

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : Autriche

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mai 2018
    Messages : 23
    Points : 11
    Points
    11
    Par défaut Tableau - résultats inadéquats d'arrondis
    salut tout le monde ,
    j'ai un soucis concernant le calcul suivant car normalement les résultats suivent un tableau
    le x varie +10 exemple : 30010;30020;30030;30040....320000
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    function IIf(b:boolean;v1,v2:Variant):Variant;
    begin
    if b then Result:=v1 else Result:=v2;
    end;
     
    function RD(r:real):real;
    begin
    Result:=R*10/10; ;
    end;
    Function dlg(x :real) :real;
    var
    r1, r2, k : real;
    begin
    x:=(Int(x / 10)) * 10 ;
     
    r1 := rd( IIf(x <= 40000, (x - 20000) * 0.23, IIf(x <= 80000, (x - 40000) * 0.27 + 4600, IIf(x <= 160000, (x - 80000) * 0.3 + 15400, IIf(x <= 320000, (x - 160000) * 0.33 + 39400, (x - 320000) * 0.35 + 92200)))));
     
    k := r1 * 0.4 ;
    r2 := IIf(rd(k) > 1500, rd(r1 - 1500), IIf(rd(k) < 1000, rd(r1 - 1000), rd(r1 * 0.6)));
     
    dlg := IIf(x < 35000, rd(r2 * 137 / 51 - 27925 / 8), r2);
     
    End ;
    End ;
    si je donne des x =
    30237,22 résultat FAUX 143.64 +0.04 normalement résultat =143.60
    30583,32 résultat FAUX 359.88 -0.02 normalement résultat =359,90
    30177,25 résultat FAUX 106.57 -0.03 normalement c : 106.60
    34350 ,22 résultat1829 JUSTE
    34599,11 FAUX ce qui est bizarre 1918
    34644,99 FAUX +0.01 1936,51 normalement c 1936.50
    je sais que Ca doit être un problème d'arrondie mais je trouve pas la solution j'attends un coup de pousse de vous , merci

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 097
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 097
    Points : 41 081
    Points
    41 081
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function RD(r:real):real;
    begin
    Result:=R*10/10; ;
    end;
    en gros vous voulez ré-écrire une fonction existante : RoundTo (arrondi "bancaire") ou SimpleRoundTo , quoique, je ne sais avec quelle version ces fonctions sont apparues.

    est-ce voulu ou est-ce parce qu'elle ne vous étaient pas connue

    Au pire (non existance) vous pourriez utiliser Round ou Frac

    voici un petit florilège
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
     
    procedure TForm2.Button2Click(Sender: TObject);
    var r : real;
    function rdTrunc(rr : real):real;
    begin
     Result:=trunc(rr*10) /10;
    // ou Result:=int(rr*10)/10
    end;
     
    function rdRound(rr : real):real;
    begin
      Result:=Round(rr*10)/10;
    end;
     
     
    begin
     
    r:=143.64 +0.04;
    memo2.Lines.add(' r = 143.64 +0.04');
    memo2.Lines.add(format('Roundto -1 %3.2f',[Roundto(r,-1)]));
    SetRoundMode(TroundingMode.rmNearest);
    memo2.Lines.add(format('SimpleRoundto roundmode rmnearest %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmDown);
    memo2.Lines.add(format('SimpleRoundto roundmode rmdown %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmUp);
    memo2.Lines.add(format('SimpleRoundto roundmode rmup %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmTruncate);
    memo2.Lines.add(format('SimpleRoundto roundmode rmtruncate %3.2f',[SimpleRoundto(r,-1)]));
    memo2.Lines.add(Format('rdRound %3.2f',[rdRound(r)]));
    memo2.Lines.add(Format('rdTrunc %3.2f',[rdTrunc(r)]));
     
    r:=359.88-0.02;
    memo2.Lines.Add('');
    memo2.Lines.add(' r = 359.88-0.02');
    memo2.Lines.add(format('Roundto -1 %3.2f',[Roundto(r,-1)]));
    SetRoundMode(TroundingMode.rmNearest);
    memo2.Lines.add(format('SimpleRoundto roundmode rmnearest %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmDown);
    memo2.Lines.add(format('SimpleRoundto roundmode rmdown %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmUp);
    memo2.Lines.add(format('SimpleRoundto roundmode rmup %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmTruncate);
    memo2.Lines.add(format('SimpleRoundto roundmode rmtruncate %3.2f',[SimpleRoundto(r,-1)]));
    memo2.Lines.add(Format('rdRound %3.2f',[rdRound(r)]));
    memo2.Lines.add(Format('rdTrunc %3.2f',[rdTrunc(r)]));
     
    r:=106.57 -0.03;
    memo2.Lines.Add('');
    memo2.Lines.add(' r = 106.57 -0.03');
    memo2.Lines.add(format('Roundto -1 %3.2f',[Roundto(r,-1)]));
    SetRoundMode(TroundingMode.rmNearest);
    memo2.Lines.add(format('SimpleRoundto roundmode rmnearest %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmDown);
    memo2.Lines.add(format('SimpleRoundto roundmode rmdown %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmUp);
    memo2.Lines.add(format('SimpleRoundto roundmode rmup %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmTruncate);
    memo2.Lines.add(format('SimpleRoundto roundmode rmtruncate %3.2f',[SimpleRoundto(r,-1)]));
    memo2.Lines.add(Format('rdRound %3.2f',[rdRound(r)]));
    memo2.Lines.add(Format('rdTrunc %3.2f',[rdTrunc(r)]));
     
    r:=1829;
    memo2.Lines.Add('');
    memo2.Lines.add(' r = 1829');
    memo2.Lines.add(format('Roundto -1 %3.2f',[Roundto(r,-1)]));
    SetRoundMode(TroundingMode.rmNearest);
    memo2.Lines.add(format('SimpleRoundto roundmode rmnearest %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmDown);
    memo2.Lines.add(format('SimpleRoundto roundmode rmdown %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmUp);
    memo2.Lines.add(format('SimpleRoundto roundmode rmup %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmTruncate);
    memo2.Lines.add(format('SimpleRoundto roundmode rmtruncate %3.2f',[SimpleRoundto(r,-1)]));
    memo2.Lines.add(Format('rdRound %3.2f',[rdRound(r)]));
    memo2.Lines.add(Format('rdTrunc %3.2f',[rdTrunc(r)]));
     
    r:=1936.51 +0.01;
    memo2.Lines.Add('');
    memo2.Lines.add(' r = 1936.51 +0.01');
    memo2.Lines.add(format('Roundto -1 %3.2f',[Roundto(r,-1)]));
    SetRoundMode(TroundingMode.rmNearest);
    memo2.Lines.add(format('SimpleRoundto roundmode rmnearest %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmDown);
    memo2.Lines.add(format('SimpleRoundto roundmode rmdown %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmUp);
    memo2.Lines.add(format('SimpleRoundto roundmode rmup %3.2f',[SimpleRoundto(r,-1)]));
    SetRoundMode(TroundingMode.rmTruncate);
    memo2.Lines.add(format('SimpleRoundto roundmode rmtruncate %3.2f',[SimpleRoundto(r,-1)]));
    memo2.Lines.add(Format('rdRound %3.2f',[rdRound(r)]));
    memo2.Lines.add(Format('rdTrunc %3.2f',[rdTrunc(r)]));
     
    end;
    et ses résultats
    r = 143.64 +0.04
    Roundto -1 143,70
    SimpleRoundto roundmode rmnearest 143,70
    SimpleRoundto roundmode rmdown 143,70
    SimpleRoundto roundmode rmup 143,70
    SimpleRoundto roundmode rmtruncate 143,70
    rdRound 143,60
    rdTrunc 143,60

    r = 359.88-0.02
    Roundto -1 359,90
    SimpleRoundto roundmode rmnearest 359,90
    SimpleRoundto roundmode rmdown 359,90
    SimpleRoundto roundmode rmup 359,90
    SimpleRoundto roundmode rmtruncate 359,90
    rdRound 359,80
    rdTrunc 359,80

    r = 106.57 -0.03
    Roundto -1 106,50
    SimpleRoundto roundmode rmnearest 106,50
    SimpleRoundto roundmode rmdown 106,50
    SimpleRoundto roundmode rmup 106,50
    SimpleRoundto roundmode rmtruncate 106,50
    rdRound 106,50
    rdTrunc 106,50

    r = 1829
    Roundto -1 1829,00
    SimpleRoundto roundmode rmnearest 1829,00
    SimpleRoundto roundmode rmdown 1829,00
    SimpleRoundto roundmode rmup 1829,00
    SimpleRoundto roundmode rmtruncate 1829,00
    rdRound 1829,00
    rdTrunc 1829,00

    r = 1936.51 +0.01
    Roundto -1 1936,50
    SimpleRoundto roundmode rmnearest 1936,50
    SimpleRoundto roundmode rmdown 1936,50
    SimpleRoundto roundmode rmup 1936,50
    SimpleRoundto roundmode rmtruncate 1936,50
    rdRound 1936,50
    rdTrunc 1936,50
    remarques :
    - je ne suis pas en total accord avec certains des résultas souhaités, il faudrait définir plus précisement ce qui est souhaité
    "359.88 -0.02 normalement résultat =359,90" 359.86 donc si arrondi "bancaire" à la dizaine 359.90 ok
    "106.57 -0.03 normalement c : 106.60" 106.54 donc si arrondi "bancaire" à la dizaine 106.50 pas 106.60

    - je n'ai pas testé votre fonction dlgx, et seulement concentré sur les arrondis

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    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 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Long débat que savoir ce que l'arrondi devrait être !

    De la lecture
    Problème d'arrondi en Delphi
    Utilisation de l'arrondi sur un calcul
    roundto simperoundto currency arrondi incorrect
    Arrondi classique vs Arrondi bancaire ou l'on évoquait déjà SimpleRoundTo et SetRoundMode en 2006.



    Real, j'éviterais aussi, moins précis que Double mais ça dépend de la version de Delphi, information que nous n'avons pas.
    A noter que Extended n'existe plus en 64Bits remplacé par Double.
    Sans parler de l'utilisation de Variant qui doit rendre cela un peu plus lent et ajoute un tas de conversion à chaque opération, va savoir ce qu'il utilise comme type lors de la conversion implicite flottant -> variant

    Ensuite, si il y a un besoin de faire des comparaison, il faut utiliser un Epsilon avec CompareValue

  4. #4
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 753
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 753
    Points : 13 336
    Points
    13 336
    Par défaut
    Je remplacerais également cette fonction IIF par un case ou if..then..else.

    On est pas ici dans une opération booléenne avec interruption du calcul dès que la condition est vraie mais dans l'appel d'une fonction dont les paramètres doivent être clairement déterminés, même si inutilisés. Ecrit ainsi, dans tous les cas les 4 IIF sont exécutés, même si x <= 40000.

    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
    Function dlg(Value: double): double;
    var
      x :integer;
    begin
      x := Trunc(Value /10) *10;
     
      case x of
        0..40000       : r1 := (x -20000)  *0.23;
        40001..80000   : r1 := (x -40000)  *0.27 +4600;
        80001..160000  : r1 := (x -80000)  *0.3  +15400;
        160001..320000 : r1 := (x -160000) *0.33 +39400;
        else             r1 := (x -320000) *0.35 +92200;
      end;
     
      ...
    Citation Envoyé par wisetechacer Voir le message
    34599,11 FAUX ce qui est bizarre 1918
    Pourtant c'est correct, 1917.97 arrondi à une décimale donne 1918.

Discussions similaires

  1. Réponses: 17
    Dernier message: 24/02/2010, 09h14
  2. Variable tableau résultat en lignes.
    Par Devmddi dans le forum Excel
    Réponses: 1
    Dernier message: 27/03/2009, 14h27
  3. click dans tableau résultat requête
    Par Pago dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 17/06/2008, 21h59
  4. [Oracle] Tableau résultat Sql et casse
    Par cbroissa dans le forum PHP & Base de données
    Réponses: 9
    Dernier message: 12/04/2006, 23h44
  5. [XSLT] numérotation des lignes du tableau résultat
    Par nemya dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 02/02/2006, 09h48

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