Перевод из двоичной системы счисления в десятичную

      Комментарии к записи Перевод из двоичной системы счисления в десятичную отключены

Главная Форумы Программирование Помощь с решением задач на Prolog Общие вопросы Перевод из двоичной системы счисления в десятичную

В этой теме 1 ответ, 2 участника, последнее обновление  Васильев Владимир Сергеевич 2 года/лет, 4 мес. назад.

  • Автор
    Сообщения
  • #2113

    questioner
    Участник

    Помогите написать на языке Prolog функцию перевода числа из двоичной системы счисления в десятичную.

    Насколько я понимаю, исходное число может быть дробным, поэтому лучше передавать его в виде строки, например:

    binary_to_decimal("1010.10", Decimal).
    Decimal = 10.5

  • #2131

    Схематично перевод показан на рисунке. Точка разделяет число на дробную и целую части. Каждому разряду числа (a[i]) в соответствие ставится вес (weight), который для целой части рассчитывается как 2^i, а для дробной — 2^(-i-1), где i обозначает удаленность разряда от точки.
    Для перевода числе достаточно вычислить сумму a[i]*weight[i].

    Перевод целой и дробной частей осуществляется по-разному, поэтому целесообразно сразу разделить число части относительно точки. Если число представлено в виде строки — то удобно использовать функцию divide_list:

    %% Number and parts introduce as strings
    number_to_integral_fractional_parts(Number, Integral, Fractional):-
    divide_list(Number, [Integral, ".", Fractional]), !.
    number_to_integral_fractional_parts(Integral, Integral, "").

    Функция разделяет исходную строку на части относительно точки. Если точки нет, то число является целым — такой случай обрабатывается отдельно.

    Так, как мы будем обрабатывать строки, а разряды нам надо обработать как числа (не как символы) — понадобится функция для преобразования символа двоичного числа в значение:

    binaryDigitSymbolToValue(48, 0):-!.
    binaryDigitSymbolToValue(49, 1):-!.

    Код символа 48 соответствует символу «0», 49 — «1». Более правильно было бы не использовать значения кодов, а применить встроенную в SWI Prolog функцию char_code. Однако, программа без особого труда переносится в Turbo Prolog и Visual Prolog, поэтому чтобы не запутывать — я не стал применять встроенные функции.

    Алгоритм перевода числа из двоичной системы счисления в десятичную можно записать так:

    • разделить число на целую и дробную части;
    • перевести части в десятичную систему счисления, пользуясь двумя разными функциями;
    • сложить результаты обработки частей.

    Тот же алгоритм на языке Prolog:

    binary_to_decimal(Binary, Decimal):-
    number_to_integral_fractional_parts(Binary, IntegralBinary, FractionalBinary),
    integral_binary_to_decimal(IntegralBinary, IntegralDecimal),
    fractional_binary_to_decimal(FractionalBinary, FractionalDecimal),
    Decimal is IntegralDecimal + FractionalDecimal.

    При переводе дробной части потребуется учитывать вес разряда, изначально равный двум, инициализация веса происходит во вспомогательной функции:

    fractional_binary_to_decimal(Binary, Decimal):-
    fractional_binary_to_decimal(Binary, 2, Decimal).
    fractional_binary_to_decimal([], _Weight, 0):-!.
    fractional_binary_to_decimal([Digit|TailDigits], Weight, Decimal):-
    binaryDigitSymbolToValue(Digit, DigitValue),
    DigitDecimal is DigitValue / Weight,
    TailWeight is Weight * 2, 
    fractional_binary_to_decimal(TailDigits, TailWeight, TailDecimal),
    Decimal is TailDecimal + DigitDecimal.

    На каждом шаге вычисляется десятичное значение разряда, посредством деления двоичного значения на вес. Вес увеличивается и рекурсивно вычисляется значение остальных разрядов. Затем значение первого разряда и хвоста складываются.

    Аналогично выполняется обработка целой части, однако при вычислении значения разряда выполняется не деление, а умножение на вес. Кроме того, перед началом работы необходимо перевернуть исходное число, т.к. индексация разрядов происходит от младших разрядов, расположенных ближе к точке. Для реверса строки используется встроенная функция reverse.

    integral_binary_to_decimal(Binary, Decimal):-
    reverse(Binary, DigitsBinary),
    integral_binary_to_decimal(DigitsBinary, 1, Decimal).
    integral_binary_to_decimal([], _Weight, 0):-!.
    integral_binary_to_decimal([Digit|TailDigits], Weight, Decimal):-
    binaryDigitSymbolToValue(Digit, DigitValue),
    DigitDecimal is DigitValue * Weight,
    TailWeight is Weight * 2, 
    integral_binary_to_decimal(TailDigits, TailWeight, TailDecimal),
    Decimal is TailDecimal + DigitDecimal.

    Вложения:

Для ответа в этой теме необходимо авторизоваться.