Download additionneur.adb


-- Additionneur de nombres binaires écrits en complément à deux.
--
-- Ce programme demande le nombre de bits utilisés pour représenter les nombres
-- en complément à deux puis demande à l'utilisateur de saisir deux nombres
-- et les additionne.
--
-- Il existe différentes opérations écrites sous forme de procédure comme :
--  * complément à un;
--  * calcul de l'opposée;
--  * soustraction;
--  * addition;
--  * saisie d'un nombre;
--  * affichage d'un nombre.
--
-- This work is in the public domain worldwide.
-- Alexandre Dupas

with Ada.Text_Io, Ada.Integer_Text_Io;
use Ada.Text_Io, Ada.Integer_Text_Io;

procedure Additionneur is
   subtype Bit is Boolean;
   type Nombre is array ( Natural range <> ) of Bit;
   Overflow : exception;

   -- Procédure de traitement (saisie, affichage)
   procedure SaisieDigit( D : out Bit ) is
      X : Integer;
   begin
      loop
         
Get(X);
         exit when X = 0 or X = 1;
      end loop;
      D := ( X = 1 );
   end SaisieDigit;

   procedure SaisieNombre( N : out Nombre ) is
   begin
      for I in N'Range loop
         
SaisieDigit( N(I) );
      end loop;
   end SaisieNombre;

   procedure AfficheNombre( N : in Nombre ) is
   begin
      for I in reverse N'Range loop
         
if N(I) then
            Put("1");
         else
            Put("0");
         end if;
      end loop;
   end AfficheNombre;

   -- Procédure d'opérations
   procedure Addition( N1, N2 : in Nombre ; N3 : out Nombre ) is
      Ret, Prev_Ret : Boolean := False;
   begin
      N3 := ( others=>False );
      for I in N3'Range loop
         
N3(I) := N1(I) xor N2(I) xor N3(I);
         Prev_Ret := Ret;
         Ret := ( N1(I) and N2(I) ) or ( Ret and ( N1(I) xor N2(I) ) );
      end loop;
      if Prev_Ret /= Ret then
         raise Overflow;
      end if;
   end Addition;

   procedure ComplementAUn( N : in out Nombre ) is
   begin
      for I in N'Range loop
         
N(I) := not N(I);
      end loop;
   end ComplementAUn;

   procedure Opposee( N : in out Nombre ) is
      Un : Nombre( N'Range) := ( 0=>True, others=>False );
   begin
      ComplementAUn( N );
      Addition( N, Un, N );
   end Opposee;

   procedure Soustraction( N1, N2 : in Nombre ; N3 : out Nombre ) is
      MoinsN2 : Nombre( N2'Range ) := N2;
   begin
      Opposee( MoinsN2 );
      Addition( N1, MoinsN2, N3 );
   end Soustraction;

   -- Début de la procédure principale
   N : Integer;
begin
   Put("Entrez la taille du codage des nombres : "); Get(N);
   declare
      subtype MesNombres is Nombre( 0..(N-1) );
      Nb_1, Nb_2, Nb_3 : MesNombres := ( others => False );
   begin
      -- Saisie
      Put("Saisie du premier nombre (bit de poid faible d'abord) : ");
      SaisieNombre( Nb_1 );
      Put("Saisie du second nombre (bit de poid faible d'abord) : ");
      SaisieNombre( Nb_2 );

      -- Préparation de l'affichage
      Put("  "); AfficheNombre( Nb_1 ); New_Line;
      Put("+ "); AfficheNombre( Nb_2 ); New_Line;
      Put("= ");

      -- Addition
      Addition( Nb_1, Nb_2, Nb_3 );

      -- Affiche le résultat
      AfficheNombre( Nb_3 ); New_Line;

   exception
      when Overflow =>
         Put_Line("erreur (dépassement de capacité)");
   end;
end Additionneur;