您当然可以在实数空间中计算它,但您可能会遇到精度问题(取决于起点)。如果您对研究轨道感兴趣,您可能更喜欢使用有理分数表示。有更有效的方法可以做到这一点,但以下代码说明了一种计算从该映射派生的序列的方法。您将在 Link 2 的第 2 页上看到 period-n 定义。您应该能够从此代码中看到如何轻松地在实数空间中工作作为替代方案(在这种情况下,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
啊……为了完整起见,这里是实值版本。纯数学家现在应该把目光移开。
% 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 阶),以至于我们真正关心的位(小数部分)不再可以在同一个双精度变量中表示。
最后一点是一种转移,它更多地与计算而不是数学有关 - 如果您的兴趣在于符号序列,请坚持第一个实现。