Большая десятичная строка в двоичную строку

Как преобразовать большое десятичное число, хранящееся в виде строки, в двоичную строку, например:

'31314232352342341239081370934702357023470' => '10101101110101000011001101011101101001100010100111111100001011'

Что вы пробовали? Подобные вопросы задавались много раз. См., например, stackoverflow.com/questions/21361627/… , stackoverflow.com/questions/59548148/… , stackoverflow.com/questions/31697957/…

Andreas Rejbrand 20.11.2022 14:56

@AndreasRejbrand Я ничего не пробовал, потому что ничего не нашел. Все ваши ссылки для совершенно разных вещей. Мое десятичное число слишком велико, чтобы его можно было преобразовать в целое число, а ваши ссылки преобразуют целые числа в двоичные.

Tom 20.11.2022 15:00

Не "совсем другой". Нисколько! :) Я мог бы написать для вас функцию позже сегодня, если кто-то не опередит меня, но, строго говоря, это не совсем то, как следует использовать переполнение стека.

Andreas Rejbrand 20.11.2022 15:02

@AndreasRejbrand Преобразование целого числа в двоичное очень просто - просто цикл получает последний бит с «и 1», а затем целое число shr 1. Преобразование шестнадцатеричного числа в двоичное также очень просто - каждая шестнадцатеричная цифра состоит всего из 4 двоичных цифр. Но с десятичной строкой я не вижу простых путей.

Tom 20.11.2022 15:14

На самом деле, это совсем не сложно. Вы можете просто сделать это очень наивно так же, как вы делаете это с ручкой и бумагой. Но я напишу для вас простую функцию позже сегодня, если только кто-то не опередит меня или Q не будет закрыт.

Andreas Rejbrand 20.11.2022 15:16

Вы можете попробовать что-то вроде rvelthuis.de/programs/bigdecimals.html , которое является частью всего github.com/rvelthuis/DelphiBigNumbers

Ron Maupin 20.11.2022 15:51

Ваш пример должен быть правильным?

Tom Brunberg 20.11.2022 16:15

@TomBrunberg Нет, это неправильно. Калькулятор Windows не мог преобразовать такое большое число.

Tom 20.11.2022 16:46
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
173
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Итак, используя деление в длину, я разработал следующий (довольно неэффективный) код:

function DecStrToBinStr(const S: string): string;

  procedure DivMod2Str(const S: string; out AQuotient: string; out ARemainder: Integer);

    function Digit(C: Char): Integer;
    begin
      Result := Ord(C) - Ord('0');
    end;

    function DigitChar(D: Integer): Char;
    begin
      Result := Char(Ord('0') + D);
    end;

    function NumDig(AIndex: Integer): Integer;
    begin
      Result := Digit(S[AIndex]);
    end;

  begin

    SetLength(AQuotient, S.Length);
    ARemainder := 0;

    if AQuotient = '' then
      Exit;

    var Q := NumDig(1);
    for var i := 1 to S.Length do
    begin
      if not InRange(Ord(S[i]), Ord('0'), Ord('9')) then
        raise Exception.Create('Invalid decimal number.');
      ARemainder := Ord(Odd(Q));
      Q := Q div 2;
      AQuotient[i] := DigitChar(Q);
      if i < S.Length then
        Q := 10*ARemainder + NumDig(Succ(i));
    end;

    while (AQuotient.Length > 1) and (AQuotient[1] = '0') do
      Delete(AQuotient, 1, 1);

  end;

const
  BitStrs: array[Boolean] of Char = ('0', '1');

begin

  if S = '' then
    Exit('');

  var L := TList<Boolean>.Create;
  try
    var T := S;
    var R := 0;
    repeat
      var Q: string;
      DivMod2Str(T, Q, R);
      L.Add(R = 1);
      T := Q;
    until T = '0';
    SetLength(Result, L.Count);
    for var i := 1 to Result.Length do
      Result[i] := BitStrs[L[L.Count - i]];
  finally
    L.Free;
  end;

end;

Это правильная, но уж точно не самая эффективная реализация.

Например, в соответствии с этой процедурой десятичное число

30347386718195039666223058436176179389328210368626940040845691245726092139866985
13829421448918578266312873948380914263473944921553341261772026398226410631065331
7294059719089452218

записывается как

11101111101001011110010001001010010100100011011010110111111000101000001111010111
00001000000111111000010100100001111100011101001010101110100101101001110100100100
01001010100110001111110111100001100111111111110101111011001001010011101000010010
00001100000001110100000101111111101111011010010011101000001000100111111010100011
10110000001010011110000101101101011101101010101011100010000011000111110010100001
01011010111110101010111100011110100100010110011110011001000100000111001110111010
01110101010100100010100001011101101001011110010110000100111010001101111000100011
111010110000001111111010010111010

в двоичном формате.

Вместо промежуточного списка я бы добавил '0' и '1' прямо в список DecStrToBinStrresult. Также нельзя было назвать DivMod2Str с (T, T, R)? И быть функцией, которая могла бы сразу вернуть R? Да, это какая-то придирка. ;-) Я просто хочу меньше многословия. И еще комментарии в коде.

AmigoJack 21.11.2022 02:40

@AmigoJack: я согласен с промежуточным списком. Я просто был ленив. (T, T, R) невозможно без некоторых других изменений.

Andreas Rejbrand 21.11.2022 09:04

Другие вопросы по теме