PDA

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


Kreoda
25.09.2009, 00:54
Такая вот лажа.Пытаюсь преобразовать дробную часть:

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.Ну,и какого... ?!

Kreoda
25.09.2009, 00:59
а к какой теме тогда

Retro
25.09.2009, 09:30
Перевод делается так, никаких двоек у тебя ни должно получится:

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......] и пока число не будет наиболее точным, умножай на двойку.

krypt3r
25.09.2009, 11:51
Писал на перле несколько месяцев назад такой код. Выложу, может, пригодится для понимания.

#!/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;
}