Tfe

Ongi etorri tfe-ren webgunera...

Old stuff/ecole_etude_fac_de_pau/licence_2/calculatrice/operations.pl

(Deskargatu)
#!/usr/bin/perl -w
#
#
#    This file is part of "CalBinaire".
#
#    Calbinaire is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License.
#
#    Calbinaire is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with Foobar; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
###############################################################################/

sub sous($$)
{
    my $ia = shift;
    my $ib = shift;
    my ($as,$bs,$ae,$be,$am,$bm); # a_signe a_exposant a_mantisse ...
    $ia =~ /(\d)(\d{8})(\d{23})/ && do { ($as,$ae,$am) = ($1,$2,$3); };	 # decoupage des variables recues
    $ib =~ /(\d)(\d{8})(\d{23})/ && do { ($bs,$be,$bm) = ($1,$2,$3); };
    
    if ($as == 0 && $bs == 1)						 # si soustraction dissimulee ...
    {
        $bs = 0;
        return add($ia,$bs.$be.$bm);
    }
    if ($as == 1 && $bs == 0)						# si soustraction dissimulee ...
    {
        $as = 0;
        return add($ib,$as.$ae.$am);
    }
    $am = "1"."$am";							# ajout du 1 implicite
    $bm = "1"."$bm";							# ajout du 1 implicite
    
    $base_exp = $ae>$be ? $ae : $be;
    $ae = bin2int($ae);
    $be = bin2int($be);
    print "Difference d'exposants : $ae et $be\n";
    print "AM :$am\nBM :$bm\n\n";
        
    while ($ae < $be )							# conversion de la mantisse de am et bm pour avoir le meme exposant ...
    {
        $am = decal_gauche($am);
        $be--;
    }
    while ($be < $ae )
    {
        $bm = decal_gauche($bm);
        $ae--;
    }
    print "Au final  : \n\tAM : $am \n\tBM : $bm \n";
    
    $rm =  soustraction($am,$bm);
    ($base_exp,$rm) = mantisse2($base_exp,$rm);
    $retour = "0".$base_exp.$rm;
    print "RETOUR FINAL : $retour\n";
    return $retour;
}





sub add($$)
{
    my $ia = shift;
    my $ib = shift;
    my ($as,$bs,$ae,$be,$am,$bm); # a_signe a_exposant a_mantisse ...
    $ia =~ /(\d)(\d{8})(\d{23})/ && do { ($as,$ae,$am) = ($1,$2,$3); };	 # decoupage des variables recues
    $ib =~ /(\d)(\d{8})(\d{23})/ && do { ($bs,$be,$bm) = ($1,$2,$3); };
    
    if ($as == 0 && $bs == 1)						 # si soustraction dissimulee ...
    {
        $bs = 0;
        return sous($ia,$bs.$be.$bm);
    }
    if ($as == 1 && $bs == 0)						# si soustraction dissimulee ...
    {
        $as = 0;
        return sous($ib,$as.$ae.$am);
    }
    $am = "1"."$am";							# ajout du 1 implicite
    $bm = "1"."$bm";							# ajout du 1 implicite
    
    $base_exp = $ae>$be ? $ae : $be;
    $ae = bin2int($ae);
    $be = bin2int($be);
#    print "Difference d'exposants : $ae et $be\n";
#    print "AM :$am\nBM :$bm\n\n";
        
    while ($ae < $be )							# conversion de la mantisse de am et bm pour avoir le meme exposant ...
    {
        $am = decal_gauche($am);
        $be--;
    }
    while ($be < $ae )
    {
        $bm = decal_gauche($bm);
        $ae--;
    }
#    print "Au final  : \n\tAM : $am \n\tBM : $bm \n";
    
    $rm =  addition($am,$bm);
    ($base_exp,$rm) = mantisse($base_exp,$rm);
    $retour = "0".$base_exp.$rm;
#    print "RETOUR FINAL : $retour\n";
    return $retour;
}








sub decal_gauche($)
{
    my $decalage = shift;
    @decalage = split //,$decalage;
    @decalage = (0,@decalage);
    pop(@decalage);
    return join("",@decalage);
}


sub mantisse($$)
{
my $base = shift;
my $rm = shift;
my $count;
print "RECU $base et $rm\n";

my @tempo = split // , $rm;
    print "Long init ".scalar @tempo."\n";
    while  (scalar @tempo > 24)
    {
    $count++;
    print "BASE ++ $base : ";
        my @base= reverse split//,$base;
        $base[0]++;
        $i=0;
        while($base[$i]>1) { $base[$i]-=2; $i++; $base[$i]++; }
        
        $base = reverse join("",@base);
    print "$base \n";
    shift(@tempo);
    $rm =  join("",@tempo);
    print "Longueur de ".scalar @tempo." : $rm !\n";
    }
    if ($tempo[0] == 1) 
	{ 
	print "On vire le 1 implicite \n";  shift(@tempo); $rm = join("",@tempo); 
	}
    else {  print "$tempo[0] != 1 !!\n"; }
    #shift(@tempo);
    #$rm = join("",@tempo);
    
print "RETOUR  $base et $rm\n";
return ($base,$rm);
}


sub mantisse2($$)
{
my $base = shift;
my $rm = shift;
my $count;
print "RECU $base et $rm\n";

my @tempo = split // , $rm;
    print "Long init ".scalar @tempo."\n";
    while  (scalar @tempo > 24)
    {
    $count++;
    print "BASE -- $base : ";

        my @base= reverse split//,$base;
        $base[0]--;
        $i=0;
        while($base[$i]<0) { $base[$i]+=2; $i++; $base[$i]--; }
        $base = reverse join("",@base);

	print "$base \n";
	shift(@tempo);
	$rm =  join("",@tempo);
	print "Longueur de ".scalar @tempo." : $rm !\n";
    }
#        my @base= reverse split//,$base;
#        $base[0]++;
#        $i=0;
#        while($base[$i]>1) { $base[$i]-=2; $i++; $base[$i]++; }
#        $base = reverse join("",@base);
    
    
    $compteur=0;
    while ($tempo[0] != 1 and $compteur<24) 
	{ 
	print "Variation ...\n";
	$compteur++;
	shift(@tempo);
	@tempo=(@tempo,0);
        my @base= reverse split//,$base;
        $base[0]--;
        $i=0;
        while($base[$i]<0) { $base[$i]+=2; $i++; $base[$i]--; }
        $base = reverse join("",@base);
	}	
    if ($tempo[0] eq 1  ) { shift(@tempo); @tempo=(@tempo,0); }
    else { $base = "0"x8; }
    $rm = join("",@tempo);

print "RETOUR  $base et $rm\n";
return ($base,$rm);
}


sub addition($$)	# addition bit a bit , sans signe, $mantisse et tout le tralala ...
{
    my $numa = shift;
    my $numb = shift;
#    print "PRET A ADDITIONER $numa et $numb\n";
    
    my @p = reverse split //,$numa;	# premier 
    my @d = reverse split //,$numb;     # deuxieme

    while (scalar @p < scalar @d) { push(@d,0); }
    while (scalar @d < scalar @p) { push(@p,0); }    

    $retenue = 0;
    for(0.. scalar @p-1)
    {
    $p[$_] += $d[$_] + $retenue;
    $retenue =0;
    if ($p[$_] > 1) { $p[$_] -= 2;  $retenue =1; }
    }
    if ($retenue ==1) { $p[scalar @p] = 1; }

    $numa = reverse join("",@p);
    $numb = reverse join("",@d);    

#    print "PRET A ADDITIONER $numa et $numb\n";
    return $numa;
}



sub soustraction($$)	# sous bit a bit , sans signe, $mantisse et tout le tralala ...
{
    my $numa = shift;
    my $numb = shift;
    print "PRET A soustraire $numa et $numb\n";
    
    my @p = reverse split //,$numa;	# premier 
    my @d = reverse split //,$numb;     # deuxieme

    while (scalar @p < scalar @d) { push(@d,0); }
    while (scalar @d < scalar @p) { push(@p,0); }    

    $retenue = 0;
    for(0.. scalar @p-1)
    {
    $p[$_] = $p[$_] - $d[$_] + $retenue;
    $retenue =0;
    if ($p[$_] < 0) { $p[$_] += 2;  $retenue =-1; }
    }
    if ($retenue ==-1) { $p[scalar @p] = 1; }

    $numa = reverse join("",@p);
    $numb = reverse join("",@d);    

    print "Resultat de l adition : $numa\n";
    return $numa;
}









sub bin2int($)
{
    my $num = shift;
#    print "RECU $num\n";
    my @num = reverse (split // ,$num);
    $var = 0;
    for (0..$#num)
    {
        $var += $num[$_]*(2**$_);
    }
    return $var;
    
}
    
    
    
    
sub int2bin($)
    {
    &clear;
    my $num = shift;;
    my @arr;
	
    undef($virgule);
    if ($num =~ /([\-\d+]+)\.(\d+)$/) { $num=$1; $virgule = "0.".$2;  }
    else {$virgule = "0"; }
    
    
    $signe = (($num >= 0) ? 0 : 1);
    print "SIGNE de $num : $signe\n";
    if ($signe) { $num*=-1; }
    my @bin;
    if ($num>0)
    {
        while ($num > 1)
        {
            push(@bin,($num%2));
            $num=int($num/2);
        }	
	push(@bin,$num);
    }
    my $puissance = (scalar @bin)-1;
    print "PUISSANCE :$puissance\n";


    @bin = reverse @bin;
    my @virg;
    $first=0;
    
    if ($virgule != 0)
    {
    $_ = 0;
    for ($puissance .. 22)
    {
#	print @virg; print "et $virgule \n";
        $virgule = $virgule * 2;
        if ($virgule >= 1)  {$first=1; $virgule -=1; @virg = ("1",@virg); }
        else {  
	    if ($num==0 and $first==0) { $puissance--; }
	    else
	    {
#		print "Ajout .. virgule : $virgule\n";
		@virg=("0",@virg); 	
	    }
	    }

    }
    }
    if ($num==0 and $virgule==0 and !$first) { $puissance=-127; }
    

    @bin = (@bin,reverse @virg);
    for(0..23) { if (!$bin[$_]) { @bin=(@bin,"0"); }}
    shift(@bin);

    my $exp=127+$puissance;
    print "Exposant finale : $exp\n";
    my $i="";
    
    for (1..7)
    {
        $i=($exp % 2)."$i";
        $exp=int($exp/2);
    }
    $i=$exp."$i";
    $retour =$signe.$i.join("",@bin);
#    print "Signe $signe\n";
#    print "Expossant : $exp = $i \n";
#    print "Mantisse ".join("",@bin)."\n";
    return $retour;
}
    

return 1;						# fin appel de operations.pl sans problemes ...