Calcul sur des entiers renvoyant un réel [Résolu]

Messages postés
152
Date d'inscription
jeudi 22 novembre 2007
Dernière intervention
21 mars 2016
- - Dernière réponse : zwyx
Messages postés
152
Date d'inscription
jeudi 22 novembre 2007
Dernière intervention
21 mars 2016
- 30 janv. 2008 à 09:25
Bonjour à tous,

J'ai constaté une erreur lors de l'exécution de mon programme. Cette erreur vient soit de moi, si j'ai oublié un détail, dans ce cas, vous pourrez m'éclaircir, soit du compilateur de Delphi 6 avec lequel je travaille.

J'ai deux entiers, de valeurs assez grande (par exemple 908652 et 19998), et selon les types desquels il sont déclarés, le calcul de leur variance peut être négatif. Je précise que je fais le calcul de la variance manuellement, en appliquant var(a,b)=(a*a+b*b-a*b)*2/9, et rappelle pour ceux qui auraient oublié leurs lointains cours de math qu'une variance ne peut par définition pas être négative.

function CalculeLaVariance1(A: Cardinal; B: Cardinal): Comp;

begin

Result := (A*A + B*B - A*B)*2/9;

end;

function CalculeLaVariance2(A: Int64; B: Cardinal): Comp;

begin

Result := (A*A + B*B - A*B)*2/9;

end;

<!-- Code colorisé via http://tools.codes-sources.com/colorizeCode.aspx -->

CalculeLaVariance1(908652, 19998) me renvoie -3723681536. Alors que CalculeLaVariance2(908652, 19998) me renvoie 1.7952825344e+11, ce qui est la bonne valeur.

J'espère ne pas être le seul chez qui cette erreur se produit. En attendant vos avis, bonne journée
Afficher la suite 

Votre réponse

5 réponses

Meilleure réponse
Messages postés
265
Date d'inscription
dimanche 7 décembre 2003
Dernière intervention
11 novembre 2016
3
Merci
dans variance1 en mettant un point d'arret et en regardant la valeur de a*a on obtient ceci
E2099 Débordement dans opération de conversion ou arithmétique
Le compilateur a détecté un dépassement dans une expression
arithmétique : le résultat de l'expression est trop grand pour être représenté
en 32 bits. Vérifiez vos calculs pour vous assurer que
la valeur peut être représentée par le matériel.

Alors que dans Variance2 le calcul ce fait sur 64Bit

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 99 internautes ce mois-ci

Commenter la réponse de fbalien
Messages postés
152
Date d'inscription
jeudi 22 novembre 2007
Dernière intervention
21 mars 2016
0
Merci
désolé pour le code qui est copié en html, je le recopie lisiblement:

function CalculeLaVariance1(A: Cardinal; B: Cardinal): Comp;
begin
  Result := (A*A + B*B - A*B)*2/9;
end;

function CalculeLaVariance2(A: Int64; B: Cardinal): Comp;
begin
  Result := (A*A + B*B - A*B)*2/9;
end;
Commenter la réponse de zwyx
Messages postés
152
Date d'inscription
jeudi 22 novembre 2007
Dernière intervention
21 mars 2016
0
Merci
Merci pour ta réponse.

Y aurait-il un moyen de déclarer quand même A et B en Cardinal, et de préciser que les calculs intermédiaires se fassent en Int64. Puisque du moment que le résultat peut être stocké dans le type de Result, ici Comp, le reste du calcul devrait être transparent.

Peut-être que quelque chose dans ce goût la ferait l'affaire:

function CalculeLaVariance3(A: Cardinal; B: Cardinal): Comp;
begin
  Result := (Int64(A)*Int64(A) + Int64(B)*Int64(B) - Int64(A)*Int64(B))*2/9;
end;
Commenter la réponse de zwyx
Messages postés
4304
Date d'inscription
samedi 16 octobre 2004
Dernière intervention
9 mars 2018
0
Merci
const

  CVrc_DDN = 2/9;
  CVrc_max64 = high(int64);

function CVrc(const A, B: LongWord): extended; overload;
begin
  Result : = (A*A + B*B - A*B) * CVrc_DDN;
end;



function CVrc(const A, B: Int64): extended; overload;
begin
  result := 0;
  if (A > CVrc_max64) or (B > CVrc_max64) then
    exit;

  Result : = (A*A + B*B - A*B) * CVrc_DDN;
end;







le type Comp ne doit pas etre utilisé, il faut preferer le type Int64, comp n'est pas un flottant, c'est un entier non scalaire contrairement aux autres types entiers (tous scalaires), c'est donc un entiers se comportant comme un flottant mais n'est pas un flottant pour autant.

on peu utiliser le type Extended en retour de fonction puisqu'il offre une trés grande pecision comparé aux autre types flottants. ou encore le type Double.

A et B, peuvent etre declaré en LongWord, Cardinal ou DWORD (unsigned int 32bit)
si il en faut plus ont peut les mettre en type Int64 avec comme limite
high(int64) ( 0x7FFFFFFFFFFFFFFF ) pour ne pas accepter les nombres negatif.










<hr size="2" width="100%" />


http://deefaze.gnomz.com
Commenter la réponse de f0xi
Messages postés
152
Date d'inscription
jeudi 22 novembre 2007
Dernière intervention
21 mars 2016
0
Merci
Merci pour toutes ce infos f0xi.

J'ai une dernière question, tellement bête que j'ose à peine la poser.
J'ai besoin d'utiliser, ou de définir, un type flottant, signé, avec une grande étendue, (de -1E10 à 1E10 par exemple). Comme personnellement, je connais comme types réels :




   Type                               Étendue
Real48                       2.9 x 10^–39 .. 1.7 x 10^38
Single                       1.5 x 10^–45 .. 3.4 x 10^38
Double                     5.0 x 10^–324 .. 1.7 x 10^308
Real                       5.0 x 10^–324 .. 1.7 x 10^308
Extended                 3.6 x 10^–4951 .. 1.1 x 10^4932
Comp                                  –2^63+1 .. 2^63 –1
Currency    –922337203685477.5808.. 922337203685477.5807



Si le type Comp est à proscrire, car entier non scalaire, il ne reste bien que le type Currency pour satisfaire mes exigences ?
Commenter la réponse de zwyx

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.