Les extended sont-ils tout pourris?

Résolu
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 - 25 oct. 2007 à 10:36
cs_Jean_Jean Messages postés 615 Date d'inscription dimanche 13 août 2006 Statut Membre Dernière intervention 13 décembre 2018 - 27 oct. 2007 à 16:36
salut tout le monde, je viens de rencontrer un probleme assez ... problematique.


j'ai voulu faire le type TRect en utilisant des extended:

type

  TExtPt = record

    X: Extended;

    Y: Extended;

  end;

  TExtRect =  record

    case Integer of

      0: (Left, Top, Right, Bottom: Extended);

      1: (TopLeft, BottomRight: TExtPt);

  end;

var

  e1, e2: TExtPt;

  exts: TExtRect;

begin

  e1.X := 1;

  e1.y := 2;

  e2.X := 3;

  e2.Y := 4;

  exts.TopLeft     := e1;

  exts.BottomRight := e2;

  //ici, exts.TopLeft = (1,2); TopRight=(3,4); mais Left=1; Top=1e-4932; Right=-3.6e-4925; Bottom=-36.85

end;


j'ai essaye de remplacer les ext par des doubles, ca marche nickel. Le
seul probleme, c'est que ma structure TExtPt est trop presente dans mon
projet pour pouvoir etre changée comme ca simplement.


Quelqu'un aurait il une idee pour me sortir de ce petrin?

Pourquoi utilise-t'on des extended (ou suis-je le seul a le faire)?


En tout cas, les extended c'est fini pour moi.

12 réponses

f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
25 oct. 2007 à 15:19
INTERFACE

Type
  TPointF = record
    X,Y: single;
  end;        
  pPointF = ^TPointF;
 
  function PointF(const X, Y: Single): TPointF; overload;
  function PointF(const Pnt: TPoint): TPointF; overload;
  function PointToPointF(const Pnt: TPoint): TPointF;
  function PointFToPoint(const PntF: TPointF): TPoint;

type
  TRectF =  record
    case Integer of
      0: (Left, Top, Right, Bottom: Single);
      1: (TopLeft, BottomRight: TPointF);
  end;
  pRectF = ^TRectF;
 
  function RectF(const TL, BR: TPointF): TRectF; overload;
  function RectF(const TL, BR: TPointF): TRectF; overload;

  function RectToRectF(const Rct: TRect): TRectF;

  function RectFToRect(const RctF: TRectF): TRect;
 
 
IMPLEMENTATION

function PointF(const X, Y: Single): TPointF;
begin
  result.X := X;
  result.Y := Y;
end;

function PointF(const Pnt: TPoint): TPointF;
begin
  result.X := Pnt.X;
  result.Y := Pnt.Y;
end;

function PointToPointF(const Pnt: TPoint): TPointF;
begin
  result.X := Pnt.X;
  result.Y := Pnt.Y;
end;

function PointFToPoint(const PntF: TPointF): TPoint;
begin
  result.X := Round(PntF.X);
  result.Y := Round(PntF.Y);
end;

function RectF(const L,T,R,B: Single): TRectF;
begin
  result.Left := L;
  result.Top  := T;
  result.Right:= R;
  result.Bottom:= B;
end;

function RectF(const TL, BR: TPointF): TRectF;
begin
  result.TopLeft := TL;
  result.BottomRight := BR;
end;
        
function RectToRectF(const Rct: TRect): TRectF;
begin
  result.Left  := Rct.Left;
  result.Top   := Rct.Top;
  result.Right := Rct.Right;
  result.Bottom:= Rct.Bottom;
end;

function RectFToRect(const RctF: TRectF): TRect;
begin
  result.Left  := round(RctF.Left);
  result.Top   := round(RctF.Top);
  result.Right := round(RctF.Right);
  result.Bottom:= round(RctF.Bottom);
end;





ça sert a rien de faire un TPoint ou TRect avec Extended, en utilisant uniquement Single tu reste avec une trés bonne precision, et de plus ça rend le code compatible avec OpenGL, DirectX et GDI+.

Packed record c'est bien pour les gros record quand la rapiditée n'est pas le soucis majeurs. l'instruction Packed ralentit fortement l'accés a ce genre de données.

de plus, extended n'est pas portable, il n'est pas dans la norme des flottants IEEE FLOAT 32 (single) ou IEEE FLOAT 64 (double)

<hr size="2" width="100%" />
http://deefaze.gnomz.com
3
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
26 oct. 2007 à 10:05
C'est bien un problème d'alignement. Tout est expliqué dans l'aide de Delphi.


L'extended fait 80bits <=> 10 octets.


Genre il met left en +0, top en +10, right en +20, bottom en +30... Comme s'ils étaient packed.


Mais un TExtPt fait 32 octets car il aligne sur des multiples de 8 pour
les extended (Encore une fois, tout est indiqué dans l'aide). Donc X
est en +0 et Y en +16.


Ce qui fait dans TExtRect :


TopLeft.X +0

TopLeft.Y + 16

BottomRight.X + 32

BottomRight.Y + 48


On peut obtenir ce genre de chiffre en faisant des truc du style :
ShowMessage(IntToStr(Integer(@monRectange.BottomRight.X) -
Integer(@monRectangle)));


Faire des packed record corrige le problème.


Mais c'est clair que les Single sont bien mieux en terme de vitesse, et
que l'on doit se reporter sur les Double si on les trouve trops
imprécis.
<hr size="2" width="100%" />3ème année en ecole d'ingé d'info cherche stage de 4 mois à partir du 01/04/08
3
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
26 oct. 2007 à 12:51
 "le resultat final soit proche de la valeur reelle"


C'est très subjectif tout ça... C'est comme dire j'en veux un peu mais pas trop.

Presque tous les jeux vidéos n'utilisent que des Single, tout en les trouvant un peu limite.


Le plus simple est de voir comment ça se passe dans ton cas. Tu peux
sans doute pas mal faciliter tes tests en définissant ton propre type :


TMonReel = Single;

<hr size="2" width="100%" />3ème année en ecole d'ingé d'info cherche stage de 4 mois à partir du 01/04/08
3
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
25 oct. 2007 à 13:29
Salut,


Peut être un problème d'alignement... Les extended sont d'une taille bizarre, style 80 bits.


Essaie de remplacer tes record par des packed record à tout hasard.

<hr size="2" width="100%" />3ème année en ecole d'ingé d'info cherche stage de 4 mois à partir du 01/04/08
0

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

Posez votre question
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
25 oct. 2007 à 15:24
Salut à tous,

De toute façon, d'après ce qu'a expliqué f0xi, le type extended n'est pas portable a 100%.

Utiliser plutôt:
Single  (norme IEEE 32 bits float)
Double (norme IEEE 64 bits float)

T'as peut-être quand même intérêt à changer ta structure, Guillemouze 


Voir:
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
25 oct. 2007 à 15:26
Quand on parle du loup...
ça se croise!   mdr
0
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
26 oct. 2007 à 11:44
merci pour toutes ces explications claires et tres precises (sauf toi cari, qui ne m'a rien apporté de plus )

Maintenant je comprend beaucoup mieux, et je vais utilise des single je pense.
Pensez vous qu'il soit mieux d'utiliser des doubles pour des calculs geometriques ou le single sera t'il suffisant? (je dois garder une precision suffisante pour qu'apres de multiples calculs intermediaires, le resultat final soit proche de la valeur reelle)

Ca confirme bien ce que je voulais, je vais supprimer la touche "x" de mon clavier comme ca je pourrai plus faire d'extended
0
cs_Jean_Jean Messages postés 615 Date d'inscription dimanche 13 août 2006 Statut Membre Dernière intervention 13 décembre 2018 3
26 oct. 2007 à 13:01
Salut Guillemouze
 Je m'imisse dans ton post car votre échange m'est très instructif. Je travaille également sur du graphique. Moi j'avais simplifié le problème en me disant que c'était un problème de résolution m'évitant ainsi de me prendre la tête.
C'est vrai que l'on met souvent des extended à tord. Les reals ou les doubles sont suffisants dans la pluspart des cas.
Personnellement j'ai pris cette mauvaise habitude lorsque j'avais besoin d'un maximum de précision pour des calculs de positions de planètes en astronomie. Certaines équations ont beaucoup de termes et il faut éliminer les résidus au maximum.
Cari ne t'a peut-être pas apporté de solution à ton problème mais il m'a fait découvrir ces normes IEEE et il peut te vendre du cacao pour pas cher d'après ce que j'ai compris!
Jean_Jean
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
26 oct. 2007 à 13:08
Je disais donc...

type TMonReel = Single;
0
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
26 oct. 2007 à 13:57
@jean_jean : la norme IEEE a ete enoncée en premier par foxi et non pas par cari ;) mais je disais ca en rigolant, les remarques de cari sont toujours tres interessantes ... sauf dans ce thread

@cari : t'a une adresse ou on peut commander des kinder suicide?

@rt15: bah je sais pas reellement la precision qu'il me faut, j'ai un paquet de calculs basés sur un paquet de calculs basés sur un pa.... et je ne sais pas trop a quel point ca peut engendrer des variations dans les resultats (par exemple un point d'un cercle calculé depuis un centre, un rayon et un angle me sert de base pour d'autre calculs, etc ...)
Mais bon, si c'est comme ca dans les jeux, les imprecisions ne doivent pas etre enormes ...

Merci
0
cs_Jean_Jean Messages postés 615 Date d'inscription dimanche 13 août 2006 Statut Membre Dernière intervention 13 décembre 2018 3
26 oct. 2007 à 15:30
Quand j'avais mis au point mes fonctions de calculs astronomiques, pour savoir jusqu'où Delphi était fidèles aux données des observatoires, j'avais utilisé quelques astuces de programmeur, du temps où j'étais encore Bon:
Je me souviens d'une (peut-être ça te donnera des idées) :
Si tu hésite entre deux types, tu créé artificiellement une petite variation à la limite des types et tu compares les résultats.
Par exemple :
   real         : 11 chif.signif. : 2,9x10(-39) … 1,7x10(+38) : 6 octects (48 bits)   =>    PI  = 3,141 592 653 6
   single      : 7  chif.signif. : 1,5x10(-45) … 3,4x10(+38) : 4 octets (32 bits)      =>    PI  = 3,141 593
   double    : 15 chif.signif. : 5,0x10(-324) … 1,7x10(+308) : 8 octets (64 bits) =>    PI  = 3,141 592 653 589 79
   extended :19 chif.signif. : 3,4x10(-4932) … 1,1x10(+4932) :10 octets(80 bits) =>PI  = 3,141 592 653 589 793 238 5
Donc si tu fais des calculs avec des variables de différents type, tu vas voir ou est ta tolérance. Ce qui est à noté, c'est que le type single a moins de chiffres de mantisse que le type real qui a un domaine d'étendu moins grand.
Bien à vous!
Jean_Jean
0
cs_Jean_Jean Messages postés 615 Date d'inscription dimanche 13 août 2006 Statut Membre Dernière intervention 13 décembre 2018 3
27 oct. 2007 à 16:36
@ Cari,
j'avais repéré ton code que j'avais téléchargé. Je le garde en réserve pour plus tard.
Je n'ai plus en tête la méthode mais je ne pense pas soit adaptée aux calculs de position.
 J'utilise deux algorythmes professionels que j'avais bidouillé. J'étais parvenu à une précision de une à 3 secondes d'arc pour la position de la Lune, ce qui est pas mal.
Ton code me sera utile sur un autre type de recherche. Si le Dieu le veux et si les journées s'allongent à 48h.
tu serais pas un peu chercheur dans l'âme Cari pour t'intéresser à ce type de calculs transcndants ne servant à rien???
Jean_Jean
0
Rejoignez-nous