Двоичное представление строки

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Аватара пользователя
runewalsh
энтузиаст
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Сообщение runewalsh »

zub писал(а):Проверку на нулевую длину никто не отменял.

Так длиннее. >_< Ну окей.

Тоже написал бенчмарк. В цикле соединяются по 3 строки, результат заведомо умещается в 255 символов.

Код: Выделить всё

{$mode objfpc}
{$coperators+}
{$macro+}

uses
  SysUtils, DateUtils;

function RandomString: ansistring;
const
  MinLen = 10;
var
  i: SizeUint;
begin
  SetLength(result, MinLen + random((256 - MinLen) div 3));
  for i := 1 to length(result) do
    result[i] := chr(ord('a') + random(ord('z') - ord('a') + 1));
end;

const
  NStrings = 1000000;
  Iterations = 15;

var
  ss: array[0 .. NStrings - 1] of shortstring;
  ss_concat: array[0 .. (NStrings + 1) div 3 - 1] of shortstring;
  ls: array[0 .. NStrings - 1] of ansistring;
  ls_concat: array[0 .. (NStrings + 1) div 3 - 1] of ansistring;
  i, ci, iteration: integer;
  dt: TDateTime;
  ms: integer;

begin
  write('Generating... (1/2) ');
  for i := Low(ss) to High(ss) do
  begin
    ss[i] := RandomString;
    if (i + 1) mod (length(ss) div 10) = 0 then write('#');
  end;
  writeln;
  write('              (2/2) ');
  for i := Low(ls) to High(ls) do
  begin
    ls[i] := RandomString;
    if (i + 1) mod (length(ls) div 10) = 0 then write('#');
  end;
  writeln(' OK');
  writeln;

{$define test :=
  write('Testing ' + typename + '... ');
  dt := Now;
  for iteration := 0 to Iterations - 1 do
  begin
    i := iteration;
    ci := 0;
    while i + 2 <= High(strings_array) do
    begin
      concatenated_array[ci] := strings_array[i] + strings_array[i + 1] + strings_array[i + 2];
      i += 3;
      ci += 1;
    end;
  end;
  ms := MillisecondsBetween(dt, Now);
  writeln('avg. ', ms / (NStrings * Iterations) * 1e6:0:2, ' ns');
  {$undef typename} {$undef strings_array} {$undef concatenated_array}}

{$define typename := 'ShortString'}
{$define strings_array := ss}
{$define concatenated_array := ss_concat}
  test

{$define typename := 'AnsiString'}
{$define strings_array := ls}
{$define concatenated_array := ls_concat}
  test
{$undef test}
end.


В худшем случае ansistring медленнее на 35%, в лучшем (достигается, если, например, в RandomString сделать постоянную длину) — вдвое быстрее, в общем, шортстринги себя не оправдывают, единственное преимущество — и то спорное.
Аватара пользователя
bormant
постоялец
Сообщения: 408
Зарегистрирован: 21.03.2012 11:26:01

Сообщение bormant »

Pasha-V писал(а):Например строка 'World'. Как узнать ее двоичное представление? Есть функция по преобразованию?

Код: Выделить всё

procedure HexDump(var m; Count: Word);
const HD: array [0..$F] of Char = '0123456789ABCDEF';
var p: ^Byte;
begin
  p:=@m;
  while Count>0 do begin
    Write(' ',HD[p^ shr 4],HD[p^ and $F]); Inc(p); Dec(Count);
  end; WriteLn;
end;

const
  s: String[9] = 'World';
begin
  HexDump(s,SizeOf(s));
end.

Вывод:

Код: Выделить всё

   05 57 6F 72 6C 64 20 20 20 20
длина  W  o  r  l  d
Pasha-V
новенький
Сообщения: 11
Зарегистрирован: 28.03.2015 03:30:52

Сообщение Pasha-V »

В Release поровну

runewalsh, убедил, у меня такой же результат. Получается, что нужно всегда использовать Release? Вообще, чем он хуже, какие минусы?

Добавлено спустя 1 минуту 38 секунд:
bormant, спасибо. Только я не профи и не понял: эти данные берутся непосредственно из памяти или это просто преобразование символов строки в их коды?
sign
энтузиаст
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

Сообщение sign »

Можно ещё и так:

1.jpg
Аватара пользователя
bormant
постоялец
Сообщения: 408
Зарегистрирован: 21.03.2012 11:26:01

Сообщение bormant »

Pasha-V писал(а):Только я не профи и не понял: эти данные берутся непосредственно из памяти или это просто преобразование символов строки в их коды?

Процедура HexDump выводит шестнадцатеричный дамп участка памяти длиной Count, начиная с адреса первого параметра (m). Поэтому для вызова мы видим, что в памяти лежит длина строки 5, следом 5 символов (да, это коды символов в 16-ричном виде) и следом мусор (компилятор дополнил типизированную константу пробелами $20, но обычно нужно ожидать там мусор).

Добавлено спустя 3 минуты 30 секунд:
sign,
Вот только одному мне кажется, что вывели вы не содержимое строки, а хранящийся в s указатель на динамическую строку? С ShortString да, было бы содержимое строки.
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

а почему на двоичное представление строки, все сразу же рекомендуют Hex? :)
может это школьно-студенческое задание?

Код: Выделить всё

{$mode delphi}
var
  s : string;
  i : integer;
begin
  readln(s);
  for i:=1 to length(s) do
    writeln(BinStr( byte(s[i]), 8 ));
end.

или более гламурный вариант

Код: Выделить всё

{$mode delphi}
var
  s : string;
  i : integer;
begin
  readln(s);
  for i:=1 to length(s) do
    writeln(s[i],': ',BinStr( byte(s[i]), 8 ),' ',hexstr(byte(s[i]), 2));
end.


ShortString-и полезны там, где нет кучи (heap) или не желательно её использование, для всяких там embedded устройств, драйверов и других загрузчиков. Ибо располагаются в стеке.
Pasha-V
новенький
Сообщения: 11
Зарегистрирован: 28.03.2015 03:30:52

Сообщение Pasha-V »

Пасиб. :)
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

Pasha-V писал(а):Пасиб. :)

Если это задача для учебного заведения. То программка выше не прокатит. Всё что от тебя хотят это вложенный цикл с ord, and и shl или shr - по вкусу. Хотя можно простым mod 2 обойтись!

Так что препод может остаться недоволен binstr()
Аватара пользователя
bormant
постоялец
Сообщения: 408
Зарегистрирован: 21.03.2012 11:26:01

Сообщение bormant »

скалогрыз,
Потому как экономнее, чем олдскульный oct. 2 против 3, или 3 против 4 с учетом пробелов разделителей.
Но не 2 против 8, как в byte to bin.
Pasha-V
новенький
Сообщения: 11
Зарегистрирован: 28.03.2015 03:30:52

Сообщение Pasha-V »

Нет, это не для учебы. Я уже давно выучился. :)
Просто хотел проверить, что происходит в памяти при операции Str := ''; Оказалось, что просто нулевой байт обнуляется, а остальные не меняются.

Добавлено спустя 23 минуты 23 секунды:
А до этого предполагал, что вся строка обнуляется. :)
Ответить