これは確かに実数空間で計算できますが、精度の問題が発生するリスクがあります (開始点によって異なります)。軌道の研究に興味がある場合は、有理分数表現で作業することを好むかもしれません。これを行うにはもっと効率的な方法がありますが、次のコードは、そのマップから派生したシリーズを計算する 1 つの方法を示しています。リンク 2 の 2 ページ目に期間 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']);
OK、これは質問ではなく回答であるはずなので、自分の質問に答えましょう...
Matlab の組み込み (および高度に最適化された)filter関数を使用して反復を処理するため、高速です (つまり、実際には、反復は M スクリプトではなく C で行われます)。Matlab では常に覚えておく価値がfilterあります。フィルタリングの問題のようには見えないアプリケーションに、それがどのように有効に使用されるかに常に驚かされます。filterただし、条件付き処理を行うことはできず、モジュロ演算をサポートしていません。単純に、このマップには、入力の全期間が出力の全期間にマップされるというプロパティがあるためです (マップ操作が整数で乗算されるため)。
前述の精度の問題にすぐにぶつかるので、それはばかげています。50 に設定num_stepsして、間違った答えが出始めるのを見てください。何が起こっているかというと、フィルター演算内の数値が非常に大きくなり (10^14 のオーダー)、実際に気にするビット (小数部分) が同じ倍精度変数で表現できなくなっています。
この最後のビットは、ちょっとした気晴らしのようなものです。これは、数学よりも計算に関係しています。シンボル シーケンスに関心がある場合は、最初の実装に固執してください。