Преобразование числа из базы B1 в базу B2 без использования промежуточной базы - PullRequest
15 голосов
/ 18 августа 2010

Есть ли способ преобразовать число из базы B1 в базу B2 без использования какой-либо промежуточной базы.

Ex:

214 от основания 5 к основанию 16 без преобразования его сначала в десятичную, а затем в десятичную в шестнадцатеричное.

-

Спасибо

Алок Кр.

Ответы [ 7 ]

8 голосов
/ 18 августа 2010

Это всего лишь артефакт того, что мы используем десятичную систему. Поэтому вы хотите (в своей голове) думать о «значении» каждого числа в десятичном виде. Таким образом, вы конвертируете все обратно в базу 10. Если бы вы знали, как выполнять деление и умножение в других базах, было бы легко конвертировать туда и обратно без использования базы 10 в качестве промежуточного звена. Большинство людей, однако, обычно не делают деление / умножение по основанию 5 и преобразуют все обратно в основание 10.

Хотя алгоритм тот же. Разделите на наибольшую мощность новой базы, которую вы можете, а затем разделите остаток на меньшую мощность, и вы получите новую базу.

Например, 0x3B для базы 5.

(математика в базе 16)

3B / 5 ^ 2 = 2 остатка 9

9/5 = 1 остаток 4

, поэтому 0x3B = 214 по основанию 5

Если вы знаете, как сделать неосновное 10 деление, это просто. Тем не менее, нет абсолютно никаких оснований для изучения этого, поэтому гораздо проще преобразовать обратно в базу 10. В качестве промежуточного шага.

Однако существует простой способ преобразования двоичного числа в шестнадцатеричное. Просто разбейте число на группы из 4 двоичных / 1 шестнадцатеричных цифр и преобразуйте цифру в цифру.

1111 0000 1100 0001 
   F    0    9    1
7 голосов
/ 19 августа 2010

Чтобы преобразовать 214 base5 в базу 16 без промежуточной базы, вам "просто" нужно знать, как рассчитать непосредственно в базе 5.

Во-первых, вам нужна таблица того, что16 цифр в базе 5 (вам нужна похожая таблица при преобразовании базы 10 в базу 16, просто ее легче держать в голове!).Эту таблицу легко создать - просто начните с 0 и увеличивайте каждую строку базы 5, пока не достигнете f в базе 16.

base 16 | base 5
--------+--------
      0 |  0
      1 |  1
      2 |  2
      3 |  3
      4 |  4
      5 | 10
      6 | 11
      7 | 12
      8 | 13
      9 | 14
      a | 20
      b | 21
      c | 22
      d | 23
      e | 24
      f | 30

Теперь вам просто нужно многократно делить на 16 (что составляет 31 1010 * base5 *).Теперь мы вспоминаем наши дни в начальной школе и используем длинное деление (если это кажется трудным, это потому, что никто не заставлял вас изучать ваши расписания в базе 5!):

Шаг 1:

   ______
31 ) 214

Шаг 2:

       3 
   ______
31 ) 214 -
     143  

Шаг 3:

       3 
   _____
31 ) 214 -
     143  
    ----
      21

Таким образом, результат 214 base5 делится на 31 base5 3 base5 остаток 21 base5 .

Это означает, что наименее значимая цифра в base16 равна 21 base5 , которую вы можете найти втаблица b base16 .Результатом деления будет 3 base5 - если бы оно было больше 30 base5 , то мы бы снова делили - но это не так, поэтому это означает, что самая значимая цифра (с использованием таблицыснова) 3 base16 .

Таким образом, ответ будет 214 base5 = 3b base16 .

7 голосов
/ 18 августа 2010

Не уверен, что вы имеете в виду. Числа в этих языках отсутствуют в базе 10 (во всяком случае, в базе 2) - когда вы форматируете число в строку, вы форматируете его с помощью базы.

Итак, если у вас есть строковое представление числа, и вы конвертируете его в число, а затем форматируете как другое основание - вы не преобразовываете в основание 10 - вы преобразовываете строку в int в строку.

Итак, если вопрос в том, как взять строку, представляющую число в базе B1, и преобразовать ее в строку в базе B2, не преобразовывая ее в int, тогда я не вижу способа сделать это легко ,

В вашем примере 214 в базе 5 это 2*5^2 + 1 * 5 + 4 - но если вы не хотите конвертировать в int, то вы этого не знаете. Это число 59 в базе 10, но компьютер видит его как 00111011. Вы можете легко отформатировать его как Hex. В конечном счете, вам все равно нужно делить и умножать и где-то хранить промежуточные результаты.

3 голосов
/ 18 августа 2010

Я не верю, что есть какой-то "синтаксический трюк", который позволяет вам сделать это для общего базового преобразования.(Уловка, которая, например, позволяет вам перейти от строки «214» к строке «3B», не выясняя, какому целому числу «214» (основание 5) соответствует).

Под этим я подразумеваю, чтовам обязательно нужно знать значение числа, с которым вы будете работать, то есть вам нужно "проанализировать" входные данные. Например,

214 в базе 5 будет проанализировано как2 * 5 2 + 1 * 5 + 4. Делая такие вычисления, вы не получите их в десятичной форме.Вы получите его в любой форме, в которой ваш компьютер решит сохранить полученное целое число (вероятно, в двоичном виде):

С этого момента вы можете легко вывести число, скажем, в базе 16. (Обратите внимание, что у вас нетпрошел через базу 10.) Как сказал @Lou Franco, вы просто перешли от string-> int-> string вместо string-> string .

2 голосов
/ 18 августа 2010

Да и нет.Да, если вы не включите тот факт, что компьютер выполняет все в двоичном формате (база 2), как другое представление.В конце концов, что является основой value в следующем коде?

long value = strtol(string, NULL, base);

В некоторых смыслах value является просто целым числом и не имеет связанной базы.Объедините это с функцией преобразования значения в строковое представление в конкретной базе, и вы можете легко перейти от строкового представления в одной базе к строковому представлению в другой базе.Поскольку промежуточного строкового представления нет, в некотором смысле промежуточное базовое значение отсутствует.

0 голосов
/ 18 августа 2010

Сохраните их как int, а затем преобразуйте, когда вам нужно представить их, как std::ios_base.

0 голосов
/ 18 августа 2010

Возможно, вы могли бы создать класс для представления каждой базы. Класс будет иметь ряд полей для представления каждой цифры - например, класс Decimal будет иметь поле единиц, поле десятков, поле сотен и так далее. Затем напишите мутаторы, чтобы сложить или вычесть единицу из значения, представленного объектом (и обработать перенос между полями), и метод доступа, который позволяет проверить, равно ли значение нулю. Создайте объект в базе и со значением входного числа (возможно, напишите метод, который анализирует строку?) И объект в нужной базе со значением ноль. Затем сделайте цикл, в котором вы вычитаете один из входного числа и добавляете один к выходному номеру, пока входной номер не достигнет нуля.

Если вы создаете объекты путем синтаксического анализа строк, вы, возможно, избежите проблемы, которая указывает на то, что вы представляете числа в двоичном виде, хотя вы, вероятно, используете унарное представление. Немного подумав, вы также можете сделать базовый класс достаточно универсальным для обработки произвольного числа баз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...