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

Ada Discussion :

Contraintes dans les calculs avec des entiers


Sujet :

Ada

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Points : 100
    Points
    100
    Par défaut Contraintes dans les calculs avec des entiers
    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
    with Ada.Text_IO; use Ada.Text_IO;
     
    procedure Essai is
    	type Entier is new Integer range -2E9 .. 2E9;
     
    	procedure Somme(X, Y: in Entier) is
    		pragma Unsuppress(Overflow_Check);
    		pragma Unsuppress(Range_Check);
    	begin
    		Put_Line(Entier'Image(X) & " + " & Entier'Image(Y) & " = " & Entier'Image(Entier'(X + Y)));
    	exception
    		when Constraint_Error => Put_Line("Erreur dans Somme");
    	end Somme;
     
    	Z: Entier := Entier'Last;
    	--E: Entier := Z + Z; -- Toujours erreur à l'exécution
     
    begin
    	Somme(Z, Z);
    end Essai;
    Je compile avec GNAT sur Mac OS X.

    Sur ma machine, l'exécution du code ci-dessus (sans les pragmas) donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     2000000000 +  2000000000 = -294967296
    Je redéfinis le type Entier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	type Entier is new Integer range -1E9 .. 1E9;
    Maintenant à l'exécution j'ai :
    Je n'en suis pas sûr, mais je pense que c'est en rapport avec RM 3.5.4 (24)

    Peut-on assumer que les types suivants lanceront toujours une exception en cas de dépassement si on les utilise avec les opérateurs prédéfinis "+" et "*" ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	Entier_Sommable_Max: constant Integer := Integer'Last / 2;
    	subtype Entier_Sommable is Integer range -Entier_Sommable_Max .. Entier_Sommable_Max;
     
    	Entier_Multipliable_Max: constant Integer := Integer(Float'Floor(Sqrt(Float(Integer'Last))));
    	subtype Entier_Multipliable is Integer range -Entier_Multipliable_Max .. Entier_Multipliable_Max;

  2. #2
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    Concernant ton premier problème, dans le RM, il y a ça :

    and their values shall be in the range System.Min_Int .. System.Max_Int.
    En fait, sur ton système, les entiers sont sur 32 bits, s'ils sont signés, ils sont sur 31 bits + 1 bit de signe.

    Ici tu fait 2*10^9 + 2*10^9 ce qui est plus grand que 2^31. d'où la valeur négative.

    Concernant la création de nouveaux types, pourquoi n'utilises tu pas un subtype ? (ton type entier)

    Concernant les exceptions, en 24, c'est bien précisé, il n'y a aucune obligation de lancer une exception. (the implementation need not raise Constraint_Error if the result is outside the base range of the type) TU peux cependant forcer le lancement d'un exception avec gnat en utilisant l'option -gnato (force un run-time check sur les overflow d'entier).

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Points : 100
    Points
    100
    Par défaut
    J'ai fait une erreur de manip lors de mon premier message : le pragma Unsuppress(Overflow_Check) n'était pas dans le programme testé.

    D'après ce que j'ai compris, RM 3.5.4 (6) dit juste que mes déclarations de types sont légales, mais ne spécifie pas le comportement lors des calculs.

    The simple_expressions of a signed_integer_type_definition shall be static, and their values shall be in the range System.Min_Int .. System.Max_Int.
    Si j'exécute :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	Put_Line(Integer'Image(Integer'First) & " " & Integer'Image(Integer'Last));
    	Put_Line(Entier'Base'Image(Entier'Base'First) & " " & Entier'Base'Image(Entier'Base'Last));
    	Put_Line(Long_Long_Integer'Image(System.Min_Int) & " " & Long_Long_Integer'Image(System.Max_Int));
    Alors j'obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    -2147483648  2147483647
    -2147483648  2147483647
    -9223372036854775808  9223372036854775807
    Mes entiers sont effectivement sur 32 bits, et si j'utilise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	type Entier is new Integer range -200_000_000 .. 2E9;
    Alors j'obtiens Constraint_Error (mais pas avec -300_000_000 par exemple, si je n'utilise ni le pragma, ni l'option "-gnato").

    Avec le pragma il y a toujours Constraint_Error (ce que je voulais) ; cela semble être comme utiliser "-gnato".

    Le fait d'utiliser type ou subtype ne semble pas avoir d'influence.

    C'est à cause de "need not raise an exception ..." que j'ai voulu utiliser Entier_Sommable et Entier_Multipliable (je voulais que leur définition oblige les résultats des calculs à être dans le "base range of the type").

  4. #4
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    Je viens de tester ton premier programme :

    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
     
    with Ada.Text_IO; use Ada.Text_IO;
     
    procedure Test is
       type Entier is new Integer range -2E9 .. 2E9;
     
       procedure Somme(X, Y: in Entier) is
       begin
          Put_Line(Entier'Image(X) & " + " & Entier'Image(Y) & " = " & Entier'Image(Entier'(X + Y)));
       exception
          when Constraint_Error => Put_Line("Erreur dans Somme");
       end Somme;
     
       Z: Entier := Entier'Last;
       --E: Entier := Z + Z; -- Toujours erreur à l'exécution
    begin
       Somme(Z, Z);
    end Test;
    Et j'ai directement le Constraint Error et donc Erreur dans Somme, c'est bien ce que tu voulais ?

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Points : 100
    Points
    100
    Par défaut
    Oui, et je confirme que sans pragma et sans "-gnato" je n'ai pas d'erreur mais un résultat négatif (j'ai GNAT 4.3.0 20070527 et un Mac Intel avec Mac OS X 10.4.9).

  6. #6
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    J'ai la même config

    Il faut absolument forcer le run-time check pour être sur de l'exécution. Il vaut mieux une exception qu'un résultat faussé.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Erreur dans des calculs avec des dates
    Par Oliv'83 dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 31/07/2008, 11h23
  2. Réponses: 6
    Dernier message: 04/07/2008, 13h59
  3. Critères avec opérateurs dans une requête avec des champs calculés
    Par lmollard dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 11/05/2008, 18h53
  4. Utiliser des Filler dans les structures avec ACCEPT
    Par beegees dans le forum Cobol
    Réponses: 2
    Dernier message: 13/01/2008, 19h09
  5. [C#] Calcul sur les dates avec des DateTimePicker
    Par alizee971 dans le forum Windows Forms
    Réponses: 10
    Dernier message: 02/04/2005, 17h14

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