Как перевести число из одной системы счисления в другую, и при этом не использовать вещественные типы данных

На вход в программу поступает два числа 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 шт):

Автор решения: Fat-Zer

Идея разложения и представления в виде дроби со знаменателем 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;
}
→ Ссылка