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

Matlab : How to represent a real number as binary

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

概念: Dyadic映射也称为Bernoulli Shift映射,表示为x(k+1) = 2x(k) mod 1。在Link2: Symbolic Dynamics中说明伯努利图是连续图,作为Shift图使用。这将在下面进一步解释。

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

问题:

伯努利位移图如何用于生成二进制序列?我这样试过,但这不是 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 页所述。

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

如果我的理解有误,请指正。

如何将实数值时间序列转换为符号化时间序列,即如何使用伯努利图对双星轨道/时间序列建模?

你当然可以用实数计算这个 space,但你可能会遇到精度问题(取决于起点)。如果您对研究轨道感兴趣,您可能更愿意使用有理分数表示法。有更有效的方法可以做到这一点,但以下代码说明了一种计算从该地图派生的系列的方法。您将在 Link 2 的第 2 页看到句点 n 定义。您应该能够从这段代码中看到如何轻松地使用实数 space 作为替代方案(在那种情况下,matlab 函数 rat 将从您的实数中恢复有理逼近)。

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

% 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

Ach...为了完整起见,这里是真正有价值的版本。纯数学家现在应该把目光移开。

% 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']);

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

速度很快,因为它使用 Matlab 的内置(和高度优化的)filter 函数来处理迭代(也就是说,在实践中,迭代是在 C 中而不是在 M 脚本中完成的)。在 Matlab 中始终值得记住 filter,我一直惊讶于如何将它很好地用于看起来不像过滤问题的应用程序。但是filter不能进行条件处理,也不支持模运算,那我们怎么办呢?仅仅因为这个映射具有 属性 输入的整个周期映射到输出的整个周期(因为映射操作是乘以一个整数)。

这很愚蠢,因为它很快就解决了上述精度问题。将 num_steps 设置为 50 并观察它开始得到错误的答案。发生的事情是过滤操作中的数字变得如此之大(10^14 阶)以至于我们真正关心的位(小数部分)不再可以用相同的双精度变量表示。

最后一点是一种消遣,它更多地与计算有关而不是与数学有关 - 如果您对符号序列感兴趣,请坚持第一个实现。

如果您只想处理有理数类型的输出,您首先必须将序列的起始项转换为有理数(如果不是)。你可以这样做:

[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 link (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