Matlab:如何将实数表示为二进制

时间:2015-05-09 06:53:33

标签: matlab signal-processing quantization

问题:如何使用连续地图 - Link1: Bernoulli Shift Map来建模二进制序列?

概念: Dyadic地图也称为伯努利移位地图,表示为x(k+1) = 2x(k) mod 1。在Link2: Symbolic Dynamics中,解释了伯努利地图是一个连续的地图,并用作移位地图。这将在下面进一步解释。

可以通过划分到适当的区域并为其分配符号来对数字轨迹进行符号化。通过写下与其轨道上的点所访问的连续分区元素相对应的符号序列来获得符号轨道。人们可以通过研究它的符号轨道来了解系统的动力学。该链接还表示伯努利位移图用于表示符号动力学。

问题:

Bernoulli移位图如何用于生成二进制序列?我尝试过这样,但这不是Link2中的文档所解释的。所以,我采用了Map的数字输出,并通过以下方式通过阈值转换为符号:

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是阈值,称为伯努利图的临界值。

我需要将实数表示为分数,如Link2第2页所述。

有人可以展示我如何应用伯努利移位图来生成符号化轨迹(也称为时间序列)?

如果我的理解错误,请纠正我。

如何将实值数值时间序列转换为符号化,即如何使用伯努利映射模拟二进制轨道/时间序列?

2 个答案:

答案 0 :(得分:6)

你当然可以在实数空间中计算它,但是你可能会遇到精度问题(取决于起点)。如果您对研究轨道感兴趣,您可能更愿意使用合理的分数表示法。有更有效的方法可以做到这一点,但下面的代码说明了一种计算从该映射派生的系列的方法。您将在链接2的第2页上看到period-n定义。您应该能够从此代码中看到如何在实数空间中轻松地工作(在这种情况下,matlab函数{{ 1}}将从你的实数中恢复一个有理的近似值。

[编辑]现在二进制序列明确!

rat

Ach ......为了完整性,这里是实值版本。纯数学家现在应该把目光移开。

% 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

并且,为了额外的信用,为什么这个实现快速但愚蠢? (提示:尝试将num_steps设置为50)...

% 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

好的,这应该是一个答案,而不是一个问题,所以让我们回答我自己的问题...

它很快,因为它使用Matlab的内置(和高度优化)% 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']); 函数来处理迭代(也就是说,在实践中,迭代是在C中完成而不是在M脚本中)。在Matlab中总是值得记住filter,我不断惊讶于它如何能够很好地用于那些看起来不像过滤问题的应用程序。但是,filter不能进行条件处理,并且不支持模运算,那么我们如何逃脱呢?只是因为这个映射具有输入的整个句点映射到输出的整个句点的属性(因为映射操作乘以整数)。

这很糟糕,因为它很快就会遇到上述精确问题。将filter设置为50并观察它开始得到错误的答案。发生了什么是过滤操作中的数字变得如此之大(10 ^ 14),我们实际关心的位(小数部分)在同一个双精度变量中不再可表示。 / p>

这最后一点是一种转移,它与计算有关而不是数学 - 如果你的兴趣在于符号序列,那就坚持第一种实现。

答案 1 :(得分:4)

如果您只想处理合理类型的输出,则首先必须将系列的起始项转换为有理数,如果不是。你可以用:

来做到这一点
[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)/DxNxDxx的分子和分母。

如果你不需要简化分母,你可以在一行中得到该系列的所有分子:

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

如果我从你的wiki链接(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