Old stuff/ecole_etude_fac_de_pau/licence_2/calculatrice/backup/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;
print "Sous de $ia - $ib\n";
my @p = reverse split("",$ia);
my @d = reverse split("",$ib);
for (scalar @p.. 31) { push(@p,"0"); }
for(scalar @d.. 31) { push(@d,"0"); }
$retenue=0;
for (0..31)
{
$somme = $p[$_] - $d[$_] + $retenue;
$retenue = $somme < 0 ? -1 : 0;
$resultat[$_] = abs($somme);
}
return join("",reverse @resultat);
}
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;
print "RECU $base et $rm\n";
my @tempo = split // , $rm;
if (scalar @tempo == 24 ) { shift(@tempo); $rm = join("",@tempo);}
else
{
print "Long init ".scalar @tempo."\n";
while (scalar @tempo > 24)
{
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";
}
#shift(@tempo);
#$rm = join("",@tempo);
}
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 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+)$/) { $virgule = "0.".$1; }
else {$virgule = "0"; }
$signe = $num > 0 ? 0 : 1;
if ($signe) { $num*=-1; }
my @bin;
while ($num > 1)
{
push(@bin,($num%2));
$num=int($num/2);
}
push(@bin,$num);
my $puissance = (scalar @bin)-1;
@bin = reverse @bin;
my @virg;
for ($puissance .. 22)
{
$virgule = $virgule * 2;
if ($virgule >= 1) { $virgule -=1; @virg = ("1",@virg); }
else { @virg=("0",@virg); }
}
@bin = (@bin,reverse @virg);
shift(@bin);
my $exp=127+$puissance;
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 ...