Как перевести число из одной системы счисления в другую, и при этом не использовать вещественные типы данных
На вход в программу поступает два числа b1 (изначальная система счисления) и b2 (та в которую нужно преобразовать) и число X (максимум 13 символов), над которым все операции и будут проводится.
Понятное дело, что сначала надо бы перевести X в десятичную систему, и с реализацией перевода целой части проблем нет.
(кстати вот она)
//r1 - целая часть числа
//char X[13];
for (; X[i] != 0 && X[i] != '.'; i++) {
r1 = (('0' <= X[i] && X[i] <= '9') ? X[i]-'0' : (('A' <= X[i] && X[i] <= 'Z') ? X[i]-'A'+10 : (('a' <= X[i] && X[i] <= 'z') ? X[i]-'a'+10 : 0))) + r1*b1;
}
Но вот как быть с дробной частью? (повторюсь, вещественные типы запрещены)
Думаю в сторону представления числа в виде обычной дроби (числитель/знаменатель).
Например преобразование 0.34 из восьмеричной системы в десятичную будет выглядеть так:
3*8^(-1) + 4*8^(-2) = 8^(-2) * (3*8 + 4) = 28 / 64
Но пока из этой идеи ничего толкового так и не получилось.
Подскажите алгоритм или просто идею для решения этой задачки.
з.ы.
Накидал примерный алгоритм. Получилось коряво, не очень рабоче, плюс по задаче возведение в степень не приветствуется. Но возможно, кого-нибудь это натолкнёт на верную мысль, коею он сможет помочь мне.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
int main(void) {
int p, tmp = 1, b1, b2, R1 = 0, R2 = 0, r1 = 0, r2 = 0, len, i = 0, j = 0, n = 1;
char X[13], ch;
scanf("%d",&b1);
scanf("%d",&b2);
scanf("%s", X); if (X[0]=='-') i++;
len = strlen(X);
for (; X[i] != 0 && X[i] != '.'; i++) r1 = (('0' <= X[i] && X[i] <= '9') ? X[i]-'0' : (('A' <= X[i] && X[i] <= 'Z') ? X[i]-'A'+10 : (('a' <= X[i] && X[i] <= 'z') ? X[i]-'a'+10 : 0))) + r1*b1;
printf("%d",r1 );
if (len == i) return 0;
else printf(".");
for (i++; X[i] != 0; i++, n = n*b1) r2 = (('0' <= X[i] && X[i] <= '9') ? X[i]-'0' : (('A' <= X[i] && X[i] <= 'Z') ? X[i]-'A'+10 : (('a' <= X[i] && X[i] <= 'z') ? X[i]-'a'+10 : 0))) + r2*b1; r2 = r2*10000000/n;
for( i = 0; i < 10; i++ ){
p = pow(10, floor(log10(abs(r2)))+1) ;
tmp = r2 * b2 / p;
r2 = r2 * b2 - tmp * p;
char ch = ((0 <= tmp && tmp <= 9) ? tmp+'0' : ((10 <= tmp && tmp <= 26) ? tmp +'A'-10 : 0));
printf("%c",ch );
}
return 0;
}
Ответы (1 шт):
Идея разложения и представления в виде дроби со знаменателем b1^n в вопросе правильная, да и идея реализации по большому счёту тоже... но вот что дорогой OP за магию со знаменателем (p) пытался сотворить, я разобраться не рискну.
В причёсанном виде всё это будет выглядеть как-то так:
int ch2n(char c) {
if ('0' <= c && c <= '9') {
return c - '0';
} else if('a' <= c && c <= 'z') {
return c - 'a';
} else if('A' <= c && c <= 'Z') {
return c - 'A';
} else {
return -1;
}
}
char n2ch(int n) {
if (0 <= n && n <= 9) {
return '0'+n;
} else if (10 <= n && n <= 35) {
return 'A'+n;
} else {
return '?';
}
}
int main(void) {
// ...
int p=1, r2=0;
for( i++; X[i] != 0; i++ ) {
r2 = r2*b1 + ch2d(X[i]);
p *= b1;
}
for( i = 0; i < 10 && r2 != 0; i++ ) {
tmp = (r2*b2) / p;
r2 = (r2*b2) % p;
putchar(d2ch(tmp));
}
return 0;
}