Matlab: как представить действительное число как двоичное

Проблема: Как использовать непрерывную карту — Link1: Карта сдвига Бернулли моделировать бинарную последовательность?

Концепция: Диадическая карта, также называемая картой сдвига Бернулли, выражается как x(k+1) = 2x(k) mod 1. В Link2: Symbolic Dynamics объясняется, что теория Бернулли Карта является непрерывной картой и используется в качестве карты сдвига. Это поясняется ниже.

Числовая траектория может быть обозначена путем разделения на соответствующие области и присвоения ей символа. Символическая орбита получается путем записи последовательности символов, соответствующих последовательным элементам раздела, которые посещает точка на своей орбите. Можно многое узнать о динамике системы, изучая ее символические орбиты. В этой ссылке также говорится, что карта сдвига Бернулли используется для представления символической динамики.

Вопрос :

Как карта сдвига Бернулли используется для генерации двоичной последовательности? Я пробовал так, но это не то, что объясняет документ в Link2. Итак, я взял числовой вывод карты и преобразовал его в символы с помощью порогового значения следующим образом:

x = rand();
 y = mod(2* x,1)  % generate the next value after one iteration

y =

    0.3295 
if y >= 0.5 then s = 1
else s = 0

где 0.5 — пороговое значение, называемое критическим значением Карты Бернулли.

Мне нужно представить реальное число в виде дробей, как описано здесь, на странице 2 Link2.

Может кто-нибудь показать, как я могу применить карту сдвига Бернулли для создания символизированной траектории (также называемой временным рядом)?

Пожалуйста, поправьте меня, если я неправильно понимаю.

Как преобразовать числовой временной ряд с действительным значением в символизированный, т. Е. Как использовать карту Бернулли для моделирования двоичных орбит / временных рядов?


person SKM    schedule 09.05.2015    source источник
comment
(Я отменил основное редактирование этого вопроса, как и все остальные).   -  person halfer    schedule 20.06.2016


Ответы (2)


Вы, конечно, можете вычислить это в реальном числовом пространстве, но вы рискуете столкнуться с проблемами точности (в зависимости от начальной точки). Если вы заинтересованы в изучении орбит, вы можете предпочесть работать с представлением рациональных дробей. Есть более эффективные способы сделать это, но следующий код иллюстрирует один из способов вычисления ряда, полученного из этой карты. Вы увидите определение периода-n на странице 2 вашей ссылки 2. Из этого кода вы должны увидеть, как вы можете легко работать в реальном числовом пространстве в качестве альтернативы (в этом случае функция Matlab rat восстановит рациональное приближение от вашего реального числа).

[EDIT] Теперь с явной двоичной последовательностью!

% start at some point on period-n orbit
period = 6;
num = 3;
den = 2^period-1;

% compute for this many steps of the sequence
num_steps = 20;

% for each step
for n = 1:num_steps

    % * 2
    num = num * 2;

    % mod 1
    if num >= den
        num = num - den;
    end

    % simplify rational fraction
    g = gcd(num, den);
    if g > 1
        num = num / g;
        den = den / g;
    end

    % recover 8-bit binary representation
    bits = 8;
    q = 2^bits;
    x = num / den * q;
    b = dec2bin(x, bits);

    % display
    fprintf('%4i / %4i  ==  0.%s\n', num, den, b);

end

Ах... для полноты, вот версия с действительным значением. Чистые математики должны сейчас отвести взгляд.

% start at some point on period-n orbit
period = 6;
num = 3;
den = 2^period-1;

% use floating point approximation
x = num / den;

% compute for this many steps of the sequence
num_steps = 20;

% for each step
for n = 1:num_steps

    % apply map
    x = mod(x*2, 1);

    % display
    [num, den] = rat(x);
    fprintf('%i / %i\n', num, den);

end

И, в довершение всего, почему эта реализация быстрая, но глупая? (СОВЕТ: попробуйте установить num_steps на 50)...

% matlab vectorised version
period = 6;
num = 3;
den = 2^period-1;
x = zeros(1, num_steps);
x(1) = num / den;
y = filter(1, [1 -2], x);
[a, b] = rat(mod(y, 1));
disp([a' b']);

Хорошо, это должен быть ответ, а не вопрос, так что давайте ответим на мои вопросы...

Это быстро, потому что он использует встроенную (и высокооптимизированную) функцию filter Matlab для обработки итерации (то есть на практике итерация выполняется в C, а не в M-скрипте). Всегда стоит помнить filter в Matlab, я постоянно удивляюсь тому, как его можно использовать с пользой для приложений, которые не выглядят как проблемы с фильтрацией. Однако filter не может выполнять условную обработку и не поддерживает арифметику по модулю, так что же нам сойдет с рук? Просто потому, что эта карта имеет свойство, согласно которому целые периоды на входе сопоставляются с целыми периодами на выходе (поскольку операция карты умножается на целое число).

Это глупо, потому что очень быстро решает вышеупомянутые проблемы с точностью. Установите num_steps на 50 и посмотрите, как он начнет давать неправильные ответы. Происходит следующее: число внутри операции фильтра становится настолько большим (порядка 10^14), что бит, о котором мы действительно заботимся (дробная часть), больше не может быть представлен в одной и той же переменной двойной точности.

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

person Rattus Ex Machina    schedule 12.05.2015
comment
Спасибо за ваш ответ. Но код не дает двоичного представления дробей. кроме того, я не могу найти разницу между первыми двумя версиями вашего кода с точки зрения возвращаемого результата - значения числителя и знаменателя одинаковы. Должны ли они быть одинаковыми или я что-то упустил? Не могли бы вы показать, как дробь в двоичном представлении, так как Вопрос заключался в том, как представлять действительные числа в двоичном с плавающей запятой? Еще раз спасибо за подробности. - person SKM; 12.05.2015
comment
Привет. Первые два дают одинаковые ответы, да, они просто вычисляют последовательность в разных пространствах. Вы можете восстановить двоичный файл... Я внесу правку. - person Rattus Ex Machina; 12.05.2015
comment
DEC2BIN преобразует неотрицательные десятичные числа в двоичную строку. Итак, мне было интересно, если одно из значений - 2/21, то как оно преобразуется в дробную двоичную систему (с использованием дополнения до двух) и, скажем, для 16-битной точности? Спасибо за другое разъяснение - person SKM; 12.05.2015
comment
Ни одно из значений не является отрицательным, я не уверен, что это знак минус или тире в вашем комментарии. 2/21 можно преобразовать в двоичное, как показано, путем увеличения некоторого коэффициента масштабирования, округления (выполненного неявно с помощью dec2bin) и преобразования в двоичное. Дробное двоичное представление - это просто ваш выбор того, где находится неявная двоичная точка. Мое редактирование выше помещает его перед двоичным числом (см. оператор fprintf) и отображает 8 двоичных битов после двоичной точки. Вы можете выбрать отображение 16, если вам нужно. - person Rattus Ex Machina; 12.05.2015
comment
Браво за большие усилия по разъяснению. - person Hoki; 12.05.2015
comment
@RattusExMachina: в этом случае отрицательных дробей нет, но в целом для других динамических систем могут быть отрицательные дроби. dec2bin явно не обрабатывает десятичные числа со знаком. Так что, вы можете также поставить это? - person SKM; 12.05.2015
comment
Я не уверен, имеет ли это отношение к исходному вопросу. Если вы представляете значение в дополнении 2, скажем, исходное свойство карты сдвига битов теряется, я думаю. Однако, если у вас есть отрицательное дробное значение x, и вы хотите получить его дополнение до двух, масштабированное до 16 двоичных дробных битов, я думаю, что dec2bin(bitxor(uint16(-x*65536), uint16(65535))+1) поможет вам в этом. Конечно, может быть более аккуратный способ;). - person Rattus Ex Machina; 12.05.2015

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

[N,D] = rat(x0) ;

Когда у вас есть числитель N и знаменатель D, очень легко вычислить ряд x(k+1)=mod(2*x(k), 1) , и вам даже не понадобится цикл.

для части 2*x(k) это означает, что все Numerator(k) будут умножены на последовательную степень 2, что можно сделать путем матричного умножения (или bsxfun для любителя функции):
поэтому 2*x(k) => в Matlab N.*(2.^(0:n-1)) (N равно скаляр, числитель x0, n — это количество членов, которые вы хотите вычислить).

Операцию Mod1 также легко перевести в рациональное число: mod(x,1)=mod(Nx,Dx)/Dx (где Nx и Dx являются числителем и знаменателем x.

Если вам не нужно упрощать знаменатель, вы можете получить все числители ряда в одной строке:

xn = mod( N.*(2.^(0:n-1).'),D) ;

но для визуального комфорта иногда лучше упростить, поэтому рассмотрим следующую функцию:

function y = dyadic_rat(x0,n)

   [N,D] = rat(x0) ;                   %// get Numerator and Denominator of first element
   xn = mod( N.*(2.^(0:n-1).'),D) ;    %'// calculate all Numerators
   G = gcd( xn , D ) ;                 %// list all "Greatest common divisor"
   y = [xn./G D./G].' ;                %'// output simplified Numerators and Denominators

Если я начну с примера, приведенного в вашей вики-ссылке (x0=11/24), я получу:

>> y = dyadic_rat(11/24,8)
y =
    11    11     5     2     1     2     1     2
    24    12     6     3     3     3     3     3

Если я начну с примера, приведенного Rattus Ex Machina (x0=3/(2^6-1)), я также получу тот же результат:

>> y = dyadic_rat(3/63,8)
y =
     1     2     4     8    16    11     1     2
    21    21    21    21    21    21    21    21
person Hoki    schedule 12.05.2015
comment
Идея диадной крысы меня немного пугает. Типа... Стивен Кинг. - person Rattus Ex Machina; 12.05.2015
comment
@RattusExMachina. Да, я знаю... странное название для функции. Я тоже так думал. Я назвал это так, потому что это было просто расширение функции dyadic, которую я дал ему в предыдущем вопросе, но на этот раз с рациональным выводом... так что отсутствие воображения я просто добавил rat к имени. Наконец-то отсутствие воображения... создал нового монстра!! - person Hoki; 13.05.2015