Показать сообщение отдельно

  #4  
Старый 25.09.2009, 11:51
krypt3r
Познавший АНТИЧАТ
Регистрация: 27.04.2007
Сообщений: 1,044
Провел на форуме:
3660186

Репутация: 905


По умолчанию

Писал на перле несколько месяцев назад такой код. Выложу, может, пригодится для понимания.
Код:
#!/usr/bin/perl                       

use strict 'vars';
use warnings;     
#use diagnostics; 

sub check_number ($$);
sub find_char ($\@);  
sub base_convert ($$$);
sub int_convert10 ($$$);

die "wrong param count\n" unless scalar @ARGV == 3;
my (%qry, $int, $frac);                            
$qry{'txt'} = shift || '72.01';#'1011101010111010';
$qry{'from'} = shift || 8;                         
$qry{'to'} = shift || 10;                          

$qry{'to'} =~ s/[^0-9]//g;
$qry{'from'} =~ s/[^0-9]//g;
if ($qry{'txt'} =~ /^(.+?)\.(.+?)$/) {
  ($int, $frac) = ($1, $2);           
  #print "NUMBERS: ", $int, " ", $frac, "\n";
} else {                                     
  $int = $qry{'txt'};                        
  $frac = 0;                                 
}                                            

die "Wrong number: integer: " unless check_number $int, $qry{'from'};
if ($frac) {                                                         
  die "Wrong number: fraction" unless check_number $frac, $qry{'from'};
}                                                                      
($int, $frac) = base_convert ($qry{'txt'}, $qry{'from'}, $qry{'to'});  
print "RESULT: $int.$frac\n";                                          
  #$qry{'txt'} =~ s/[^0-9a-f]//g;                                      
exit 0;                                                                

sub check_number ($$) {
  my ($num, $ss) = @_; 
  my ($i, $b, @chars, $d);
                          
  for $i (0 .. $ss - 1) { 
    $chars[$i] = ($i < 10 ? $i : chr ($i + 0x57));
  }                                               
  $b = 1;                                         
  foreach $d (split //, $num) {                   
    if (!find_char ($d, @chars) == 1) {           
      $b = 0;                                     
      last;                                       
    }                                             
  }                                               
  return $b;                                      
}                                                 

sub find_char ($\@) {
  my ($char, $arr) = @_;
  my ($elem, $b);       
                        
  $b = 0;               
  foreach $elem (@$arr) {
    if ($char eq $elem) {
      $b = 1;            
      last;              
    }                    
  }                      
  return $b;             
}                        

sub base_convert ($$$) {
  my ($num, $from, $to) = @_;
  my ($int, $frac, $res);    
                             
  #print $num, "\n";         
  if ($num =~ /^(.+?)\.(.+?)$/) {
    ($int, $frac) = ($1, $2);    
  } else {                       
    $int = $num;                 
    $frac = 0;                   
  }                              
  #print $frac, "\n";            
  if ($from != 10) {             
    $int = int_convert10 ($int, $from, 1) if $int;
    $frac = int_convert10 ($frac, $from, 0) if $frac;
  }                                                  
  print "DEC: $int $frac\n";                         
  $int = int_convert ($int, $to, 1) if $int;         
  $frac = int_convert ($frac, $to, 0) if $frac;      
                                                     
  return ($int, $frac);                              
}                                                    

sub int_convert10 ($$$) {
  my ($num, $from, $isint) = @_;
  my ($j, $res, $i, @digit);    
                                
  #print "NUM: ", $num, "\n";   
  @digit = split //, $num;      
  $j = $#digit;                 
  if ($isint) {                 
    for $i (0 .. $#digit) {     
      if ($digit[$i] =~ /^\d{1}$/) {
        $res += $digit[$i] * $from ** $j--;
      } else {                             
        $res += (ord ($digit[$i]) - 0x57) * $from ** $j--;
      }                                                   
    }                                                     
  } else {                                                
    for $i (0 .. $#digit) {                               
      if ($digit[$i] =~ /^\d{1}$/) {                      
        $res += $digit[$i] / ($from ** ($i + 1));         
        #print $digit[$i], "\n";                          
      } else {                                            
        $res += (ord ($digit[$i]) - 0x57) / ($from ** ($i + 1));
      }                                                         
    }                                                           
  }                                                             
  $res =~ s/^0\.//;                                             
  #print "RES: ", $res, "\n";                                   
  return $res;                                                  
}                                                               

sub int_convert ($$$) {
  my ($num, $to, $isint) = @_;
  my ($ost, $res, $cnt);      
                              
  #print $num, "\n";          
  if ($isint) {               
    while ($num > 0) {        
      $ost = $num % $to;      
      if ($ost < 10) {        
        $res .= $ost;         
      } else {                
        $res .= chr ($ost + 0x57);
      }                           
      $num = int ($num / $to);    
    }
    $res = join '', reverse (split //, $res);
    #print $res, "\n";
  } else {
    $num = '0.' . $num;
    $ost = 1;
    $cnt = 0;
    #print $num, "\n";
    while (($ost > 0) && ($cnt < 9)) {
      #print "\n=======\n", $num, "\n";
      $num *= $to;
      #print $num, "\n";
      $ost = $num - int ($num);
      #print $ost, "\n";
      if (int ($num) < 10) {
        $res .= int ($num);
      } else {
        $res .= chr (int ($num) + 0x57);
      }
      #print $res, "\n";
      $num = $ost;
      #print $num, "\n";
      $cnt++;
    }
    #$res = $res;
    #print $res, "\n";
  }
  return $res;
}