Floating point

Résolu
ethan_decoster Messages postés 38 Date d'inscription mardi 31 janvier 2006 Statut Membre Dernière intervention 4 avril 2008 - 7 août 2006 à 18:25
twh19 Messages postés 4 Date d'inscription mercredi 4 août 2004 Statut Membre Dernière intervention 5 janvier 2009 - 17 oct. 2007 à 18:30
Dans une base de donnée utilisée pour un de mes programmes, j'ai des données qui ont comme type de champs la valeur reel simple. La base de donnée communique avec le programme via Ado. Donc dans la base de donnée j'ai les valeurs 26.3. Mais a l'affichage dans le programme, la valeur de ce champs est de 26.299365489 ce qui en valeur arrondie me donne 26.3.

Mais le hic ce que je me sert de cette donnée pour en afficher d'autre. Mais comme le programme intercepte la valeur de 26.3 comme 26.299... les autres donnée ne sont donc pas affichée. De plus c'est valeur doit etre de type numérique et non chaine de caractère parce que j'utilise le tri numérique pour ordonnancer ces données...

Le pire c'est quand je fais un query sur ma table du style select * from clc where (cas = 26.3), le query me trouve l'enregistrement.

Quelqu'un saurait me dire pourquoi la basse de donnée me donne la valeur de 26.3 alors que le programme affiche la valeur de 26.299...

Merci
Jerome

10 réponses

cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
7 août 2006 à 18:57
Salut,

Cela vient de la manière dont est stocké la valeur en mémoire (du PC).

Pour faire dans le simplifié, Les nombres flotant sont stocké sous la forme "scientifique" cad 'base' x 10~'Puissance' (+signe)

La base est stocké avec un nombre finit de bit (disons 15 pour l'exemple).

Donc quand tu écrit 26.3, il vas arrondire la base (263) au nombre le plus pres d'une puissance de 2 (1 à 2^15-1).

Après quand tu "relit" la valeur, il te retourne toute la précision qu'il a (26299...). Même celle que tu ne lui a pas donné.

C'est pour ça qu'il ne FAUT JAMAIS FAIRE DE TEST D'EGALITE AVEC DES FLOTANT !!!!

C'est aussi pour ça que tu peut additionner 1e-10 à une var floatant qui vaut 10e40 pendant toute une journée sans que la var ne change de valeur.

fait un test genre :

(cas < Limit + Epsilon) and (cas > limit - Epsilon)

avec un Epsilon qui vaut genre 0.002. (enfin, ça dépend de bcp de choses)

Chaque fois que possible, évite les type flotant, remplace les par des integer avec une ponderation (facteur).


"De plus c'est valeur doit etre de type numérique et non chaine de caractère parce que j'utilise le tri numérique pour ordonnancer ces données..."

je connais pas les détail de ton cas, mais il y a surement un moyen de le lire directement en floatant.

bon code,
3
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
8 août 2006 à 05:22
utilise la virgule fixe.

26.3 = 2630/100 << depend de l'interval Min..Max des chiffres et de la precision voulue 1..n decimales

stockage en entiers : round(Float*100)

si je joue dans l'interval : 0..1000 avec precision maxi de 3 decimale, je multiplie par 1000
Fin := round(F*1000);
Fout := Fin/1000;

le tri de chaine en valeur flottante risque de faire n'importe quoi ...

en tout cas on index pas des valeurs avec des flottant justement a cause de ça.

champs ID : int / unique / auto increment / non null
champs Valeur : float / null

<hr size="2" width="100%" />Croc (click me)
3
ethan_decoster Messages postés 38 Date d'inscription mardi 31 janvier 2006 Statut Membre Dernière intervention 4 avril 2008
7 août 2006 à 18:52
Ah oui une chose importante peut etre, la valeur de 26.3 dals la base de donnée est recupérée avec le composant DBEdit. C'est peut etre ca le probleme... Je check et vous tiens au courant...

Si quelqu'un, trouve avant moi, merci de poster vos commentaires...

Jerome
0
ethan_decoster Messages postés 38 Date d'inscription mardi 31 janvier 2006 Statut Membre Dernière intervention 4 avril 2008
7 août 2006 à 19:03
Y pas une solution pour lire le nombre comme il est tape dans la base de donnée??
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
7 août 2006 à 19:05
oui, il faut utiliser un champ string pas floatant.

ou si t'as toujours la même précision lors de la saisie, fait une routine de formatage.
0
ethan_decoster Messages postés 38 Date d'inscription mardi 31 janvier 2006 Statut Membre Dernière intervention 4 avril 2008
8 août 2006 à 00:48
Avec une chaine string, tu sais faire un tri numerique sur les donnees??
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
8 août 2006 à 11:51
au pire des pire, fait un champs en flotant que tu utilise pour le tri et un en string pour avoir ta "saisie". (très moche)

Mais j'éviterais si j'étais toi, y a surement un moyen de résoudre ton problème en changeant deux-trois trucs dans ton system.

De toute façon, tu peux marquer 'dommage' pour faire un test d'égalité (unique) avec un flotant.
0
ethan_decoster Messages postés 38 Date d'inscription mardi 31 janvier 2006 Statut Membre Dernière intervention 4 avril 2008
8 août 2006 à 17:45
oui c'est vrai que c'est moche comme solution. J'ai fait changer le fusil d'epaule de loa sncb qui a abandonner le projet de mettre un cas intermedaire. Ex: 26 26BIS et 27 (si je les mettais en chaine de caractere) j'aurais pas eu cet ordre la. Maintenant la solution etait de garder le champs numerique mais de mettre 26 26,1 et 27 dans la base de donnée. Mais le projet a ete abandonné. Merci pour ton explication Loda j'avais pas capté cela comme ca mais c'est vrai que les float c'est de la M....

Jerome
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
8 août 2006 à 18:25
de rien.

si j'ai bien compris, tu utilise la partie fractionnaire de ton float pour distinguer des cas?!

pourquoi tu n'utilise pas un champs supplémentaire ? cela te permeterait de faire ton trie facilement.

(les float c'est fait pour manipuler des valeurs floattant. faut pas s'en servire pour autre choses.)

bon code,
0
twh19 Messages postés 4 Date d'inscription mercredi 4 août 2004 Statut Membre Dernière intervention 5 janvier 2009
17 oct. 2007 à 18:30
procedure TForm1.Button1Click(Sender: TObject);
var a,b,c,d,e,f,n,o,k: string;
    i,j,g,m,x,y,v: integer;
    tr: boolean;
begin
j := 0;
k := '';
tr := false;while (j <length(edit1.Text)) and (tr false) do
   begin
     k := edit1.Text[j];
     if k = '.' then
       begin
        tr := true;
        v := j;
       end;
     j := j + 1;
   end;
if tr = true then
begin if (length(edit1.Text) - v 1) or (length(edit1.Text) - v 2)  then
  edit2.text := edit1.Text
else
begin
i := 1;
m := 0;
c := '';
b := '';
while i <= length(edit1.Text) do
  begin
     c := edit1.Text[i];
     b := b + c;
      if c = '.' then
        begin
          a := b;
          m := i;
        end;
     i := i + 1;
  end;
d := edit1.Text[m + 1];
e := edit1.Text[m + 2];
f := edit1.Text[m + 3];
n := d + e;
if StrToInt(f) >= 5 then
  begin
    g := StrToInt(n) + 1;
    n := IntToStr(g);
    if g = 100 then
        begin
          o := '';
          for x := 1 to m - 1 do o := o + a[x];
          y := StrToInt(o) + 1;
          edit2.Text := IntToStr(y);
        end
       else
           edit2.Text := a + n;
  end
     else
       begin
         edit2.Text := a + n;
       end;
end;
end
  else
    edit2.text := edit1.Text;
end;

The joy of the life is to do a work that nobody made and that nobody it imagined
0
Rejoignez-nous