Перевод из дробных чисел в другие системы счисления

Discussion in 'Болталка' started by Kreoda, 25 Sep 2009.

  1. Kreoda

    Kreoda New Member

    Joined:
    9 Sep 2009
    Messages:
    20
    Likes Received:
    0
    Reputations:
    0
    Такая вот лажа.Пытаюсь преобразовать дробную часть:

    0.853 к примеру перевести из 10 в 2:

    0.853*2 = 1.706
    0.53*2 = 1.06
    0.3*2 = 0.6

    0.853 = 1102 должно быть.Проверяю:

    0.1102 = 1*2 ^-1 + 1*2 ^-2 + 0*2 ^-3 = 0.5+0.25 = 0.75.Ну,и какого... ?!
     
  2. Kreoda

    Kreoda New Member

    Joined:
    9 Sep 2009
    Messages:
    20
    Likes Received:
    0
    Reputations:
    0
    а к какой теме тогда
     
    #2 Kreoda, 25 Sep 2009
    Last edited by a moderator: 30 Sep 2009
  3. Retro

    Retro New Member

    Joined:
    4 Jun 2009
    Messages:
    3
    Likes Received:
    3
    Reputations:
    0
    Перевод делается так, никаких двоек у тебя ни должно получится:

    0.853*2 = 1.706 - первую цифру всегда выкидываем т.е 1
    0.706*2 = 1.412 - опять единичку выкидываем, оставляя только дробную часть.. 1
    0.412*2 = 0.824 - оставляем ноль. 0
    0.824*2=1.648 - единичку выкидываем 1
    0.648*2=1.296 = 1
    и т.д.

    Т.е получилось что-то вроде [0.110111......] и пока число не будет наиболее точным, умножай на двойку.
     
  4. krypt3r

    krypt3r Elder - Старейшина

    Joined:
    27 Apr 2007
    Messages:
    1,507
    Likes Received:
    389
    Reputations:
    101
    Писал на перле несколько месяцев назад такой код. Выложу, может, пригодится для понимания.
    Code:
    #!/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;
    }