Arrondi en delphi

Arrondi en delphi - Delphi/Pascal - Programmation

Marsh Posté le 20-01-2004 à 18:08:23    

salut,
La fonction round de delphi ne marche pas comme je veut :
Elle arrondi au plus proche, si on est juste au milieu, elle arrondi au nombre pair le plus proche (??).
par exemple  
round(1.4)=1
round(1.5)=2
round(1.6)=2
round(2.5)=2 (??)
round(2.6)=3
 
Moi je voudrais arrondir au plus pres, et si on est au milieu, arrondir au dessus
round(2.5)=3
 
ca fait 1h que je google, mais je trouve rien, ou plutot je trouve des explications tres compliqué qui font intervenir de l'assembleur.
 
par exemple :

Code :
  1. type
  2.     TRoundMode = (rmNearest, rmDown, rnUp, rmTruncate);
  3. { Return the FPU control word }
  4. function GetControlWord: Word; assembler;
  5. var
  6.   Ctl: Word;
  7. asm
  8.   fstcw Ctl
  9.   mov ax, Ctl
  10. end;
  11. { Set the FPU control word }
  12. procedure SetControlWord(Ctl: Word); assembler;
  13. asm
  14.   fwait
  15.   fldcw Ctl
  16. end;
  17. { Set the rounding mode and return the old mode }
  18. function SetRoundMode(RoundMode: TRoundMode): TRoundMode;
  19. var
  20.   CtlWord: Word;
  21. begin
  22.   CtlWord := GetControlWord;
  23.   SetControlWord( (CtlWord and $F3FF) or (Ord(RoundMode) shl 10) );
  24.   Result := TRoundMode((CtlWord shr 10) and 3);
  25. end;


 
delphi ne comprend pas le fldcw de la fonction setcontrolword,  
 
help !
 
merci
 
 

Reply

Marsh Posté le 20-01-2004 à 18:08:23   

Reply

Marsh Posté le 20-01-2004 à 18:19:15    

je me rend compte que j'ai pas été tres precis sur l'erreur :
 
message "Combinaison incorrecte d'instruction et de paramètres" sur la ligne qui comprend le 'fldcw' dans la fonction SetControlWord

Reply

Marsh Posté le 20-01-2004 à 20:12:43    

tout simple :
 
n := Trunc(n + 0.5);
 
le Round de Delphi est la méthode "statistique", le coup de "arrondir au-dessus si .5" c'est la méthode "commerciale".


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 21-01-2004 à 00:41:42    

:whistle:  
 
 
merci  :jap:

Reply

Marsh Posté le 21-01-2004 à 10:33:47    

Comme je veut arrondir a 3 chiffres, j'ai ecrit cette fonction :
 

Code :
  1. Function myRound(value: Real):Real;
  2. begin
  3.   result:=Trunc(value*1000+0.5)/1000.0;
  4. end;


 
mais ca reagis un pas comme je le souhaite :
 
myRound(5.0004)=5
myRound(5.0005)=5 (??)
myRound(5.0006)=5.001
 
un truc que je ne n'explique pas :
myRound(0.0005)=0.001
myRound(1.0005)=1
myRound(2.0005)=2.001
myRound(3.0005)=3.001
myRound(4.0005)=4
myRound(5.0005)=5
myRound(6.0005)=6
myRound(7.0005)=7
myRound(8.0005)=8.001
 
trouvez la suite logique


Message édité par nico168 le 21-01-2004 à 10:34:19
Reply

Marsh Posté le 21-01-2004 à 10:40:04    

les nombres flottants en Delphi et dans tous [edit: la plupart] les autres langages ne sont que des approximations
7.0005 est peut-être stocké comme 7.0004999999999999


Message édité par antp le 21-01-2004 à 10:46:09

---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 21-01-2004 à 10:45:09    

Avec la fonction suivante, ça fonctionne comme il faut :

Code :
  1. function MyRound(const Value: Extended): Extended;
  2. begin
  3.   Result := Trunc(Value * 1000 + 0.5) / 1000.0;
  4. end;


(d'ailleurs toutes les fonctions de Delphi prennent des Extended et non des Double/Real ou des Single ;))


Message édité par antp le 21-01-2004 à 10:45:36

---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 21-01-2004 à 10:57:58    

X et Y etant des nombres decimaux lu dans un fichier texte et converti avec strtofloat
comment m'y prendre si je veut que X divisé par Y soit arrondit correctement ?

Reply

Marsh Posté le 21-01-2004 à 11:04:41    

J'ai essayé en remplaçant Real par Extended, c'est mieux, je suppose que l'approximation est plus precise, mais il y a encore des cas ou cela marche pas :
 
myRound([1à7].0005)=[1à7].001 <- ok
myRound(8.0005)=8

Reply

Marsh Posté le 21-01-2004 à 12:12:49    

Code :
  1. function MyRound(const Value, Prec: Extended): Extended;
  2. begin
  3.   Result := Trunc(Value * 1000 + 0.5 + Prec) / 1000.0;
  4. end;


 
en passant comme second paramètre la précision, genre 0.0000001
ça fait bidouillage mais je ne vois pas trop quoi faire d'autre :/ (c'est le Trunc qui fait perdre la précision en fait)


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 21-01-2004 à 12:12:49   

Reply

Marsh Posté le 21-01-2004 à 12:16:53    

Sinon en Delphi 6 & 7 (ça n'existe pas dans les précédents) tu peux faire ceci :
 

Code :
  1. SetRoundMode(rmTruncate);
  2.   n := Round(n * 1000 + 0.5) / 1000;


vu que le bidule avec de l'assembleur que tu as mis dans ton premier post fait partie des fonctions de Delphi
 
ça a l'air de mieux marcher, mais il faut voir si ça va dans tous les cas


Message édité par antp le 21-01-2004 à 12:18:48

---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 21-01-2004 à 14:54:22    

je suis en delphi5, j'ai donc pas de SetRoundMode, le code dans mon premier commentaire etait sensé palier ce manque.
 
Je vais utiliser ta fonction qui fait le bidouillage (+0.00001) a defaut de trouver autre chose.
 
merci encore Antp  :jap:

Reply

Marsh Posté le 21-01-2004 à 15:06:27    

J'ai essayé de récupérer les bouts de code de Delphi 6 de ces fonctions et de les coller en Delphi 5, mais il arrondit toujours au-dessus :/


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed