暗号化のための変換の応用2(作成中)


update: 9/08/2008

暗号理論の応用を試みた行列変換のあれこれ。そのレポートの続きです。

Top Page へ

Contents

 逆行列変換フローチャート
 3x3行列の場合
 2x2行列の場合
 4x4〜10x10行列の場合
 結論
 サンプルプログラム
 改良結果

 逆行列変換フローチャート 掃出し法のアルゴリズムはエラー要因を良く考慮したものがありますが、 改めて作成してみるとプログラム言語の影響と思われる部分もありました。 [アスキーデータの行列化]    | [ det = 0 ] --- yes --- [ (a) 他の変換 ] | [ 掃出し法 A → A-1 ] | [ 小数点 n 桁での打切り B = A-1 - ε(n+1) ] | [ ファイルに保存 ] | [ ファイルから読出し ] | [ 掃出し法 B → B-1 ] | [ 復元精度の比較 B-1 = A ? ] --- no --- [ (b) 他の変換 ] | [ 小数点桁 n の利用 ]

top


3x3行列の場合 3x3 行列での実験プログラムでは、nと復元失敗の関係は次のようになりました。 英数文字62=? の組合せからランダム抽出で1000回を10セット試験します。
保存桁n / セット123456789 10割合
471168468966669471568770871069670%
51211130324 - 0.4%
60201220312 - 0.3%
71201013521 - 0.5%
計算のように4桁ではありませんが、5桁からはほぼ完全に復元できました。 保存桁を増やしても精度が改善されないのは、復元行列を整数へ 近似する時にエラーが起きてたのが原因でした。 例えば復元の結果 65.000123 という値になったのに、整数変換して整数 65 と 比較一致すると False 判定がでます。 整数値の比較方法としては、次のものが考えられます。 @ 四捨五入の方法   a) Int 型でのキャスト。(int)1.99 = 1.0 のように切下げになるのを利用する。   b) Java には、最も近い整数に変換する Math.rint(double) が   用意されているので、これを使う。 A 極限値の考え方  2数の差の絶対値により評価します。Math.abs(a-b)<= 0.00001 のような判定です。 @の方法が当初のプログラムでしたが、Aの方法に変更しました。 整数値への四捨五入ですので、差が 0.5 以上の場合、復元失敗と見なします。
保存桁n / セット123456789 10割合
471770470270170769670169866369870%
50000100000 - 0.01%
60001000000 - 0.01%
なぜ@の方法では駄目なのでしょう? Math.rint() メソッドにエラーが無いならば、 A==B の数値判定では、初期化後に代入した数値と、演算後に代入した数値では ビット的な差がでる場合があるのかもしれません。 Aの方法でも残るエラーは、教科書通りにピボットがゼロとなる例でした。 2桁以上の例はあまり見かけないので記録しておきました。 98 101 75 80 112 117 98 101 79 85 119 67 76 101 112 52 115 82 2行目と3行目を交換すると、無事に計算できますが、交換行の記録が必要になり、 0.01% ほどなので、この場合は逆行列変換は中止しました。

top


2x2行列の場合 3x3行列で思わぬエラーが出たので、2X2行列も丁寧に調査しました。
保存桁n / セット123456789 10割合
397497497097597896496996998397897%
4399391366403421384382383401435 40%
50010000000 0.002% (5回に1回ぐらい)
61000000000 0.002% (5回に1回ぐらい)
計算と異なり、5桁までの保存が必要でした。 0.002% のエラーの原因は特殊な場合に起きるゼロ計算エラーでした。 次の行列式はいずれもゼロですが、double 型の関数呼出で計算した値は 大きな負の値になっていました。 double det=det2(a,b,c,d); ... public static double det2(double a, double b, double c, double d){ double detr=a*d-b*c; return detr; } 70 76    87 120 105 114 → det = -6.36804E7 87 120 → det = -9.43035E7 念のため、50 〜 120 の値で行列式を計算すると、 50x50 - 50x50 = -6.25E6 120x120 - 120x120 = -2.0736E8 のように変化していきます。1を足すと、-6249999 のようになるので、 プログラムとしては、負の数として認識しています。 関数呼出でも引き算ではこのような現象は起きず、関数呼出せずに、 ベタで書いても( double det=a*d-b*c ; ) このような計算エラーは起きませんでした。 論理演算での符号ビット、補数表現などが関係していそうですが、 エラーメッセージがあってもよさそうです。

top


 4x4〜10x10行列の場合 4x4
保存桁n / セット123456789 10割合
4883885896868901894886870868877 88%
50100000000 0.005% (2回に1回ぐらい)
5x5
保存桁n / セット123456789 10割合
498297696996796796596496795896597%
50311110101 0.1 - 0.3%
60000100000 0.002% (5回に1回ぐらい)
7x7
保存桁n / セット123456789 10割合
4100099899699899899599799299599899%
519202326212630171726 - 0.6% (10回に3回ぐらい)
60010000000 0.01%
10x10
保存桁n / セット123456789 10割合
499699799799599999899599899999899%
5146166144158144148158166176150 15%
60001000000 0.005% (2回に1回ぐらい)
最後まで残ったエラーは、やはり掃出し法のピボットがゼロとなるケースでした。 105 115 66 108 57 106 102 77 53 106 106 112 54 57 56 86 89 55 90 53 121 89 55 88 86 72 74 48 76 107 121 113 66 49 78 120 84 57 121 50 70 107 116 119 74 106 86 78 107 116 102 109 115 88 81 88 52 99 50 116 119 70 118 78 76 88 68 54 100 55 67 84 118 89 84 108 104 99 50 57 83 69 99 87 102 102 106 73 122 78 50 55 74 109 71 86 53 54 99 68 100 110 55 100 120 81 98 116 84 122 108 103 100 89 66 109 104 114 66 51 98 78 65 112 51 84 102 71 80 80 82 103 113 121 71 87 105 69 57 67 53 118 80 50 70 74 113 112 87 104 107 87 98 66 55 67 51 55 107 121 103 78 78 121 70 122 54 121 69 53 71 110 68 52 80 78 109 107 87 122 68 113 57 75 74 77 117 76 106 54

top


 結論
行列次元安全な保存小数点桁数復元失敗の確率 %保存容量の増加(byte)
2x250.002 16 → 64
3x350.01 36 → 126
4x450.005 64 → 224
5x550.002 100 → 350
7x760.01 196 → 686
10x1060.005 400 → 5600
文字数はnで、1文字を2桁の数字と考えると Unicode では4byteです。 よって当初の 4n から、5桁の場合は14nで 3.5倍、 6桁の場合は16nで4倍ぐらいの保存容量の増加があります。

top


 サンプルプログラム ダウンロード ( Java )

top


 改良結果 実装中...

top


調査レポート作成 :tmlbworks