質問

Safer+を実装するために、バイトで非線形関数を実行しようとしています。アルゴリズムでは、バイトでベース45対数を計算する必要があり、その方法がわかりません。

ログ45(201) = 1.39316393

これをバイトに割り当てると、値は1に切り捨てられ、正確な結果を回復できません。

私はこれをどのように処理することになっていますか?

役に立ちましたか?

解決

暗号化はしばしば使用します プライムフィールド、 この場合、GF(257)。 指数テーブルを作成します それは次のように見えます:

exp | log
----+----
  0 |   1
  1 |  45
  2 | 226
  3 | 147
... | ...
128 |   0
... | ...
255 |  40
---------

「ログ」値は45ですexp %257。 modPow このテーブルを構築するための関数(電力に数字を上げ、何らかの価値をモジュロ)します。通常はゼロの対数が未定義であるため、「EXP」128の値は特別なケースであることがわかります。

「ログ」列でITを見つけることにより、数値の対数を計算します。その行の「exp」列の値は対数です。

これが初期化のスケッチです:

BigInteger V45 = new BigInteger(45);
BigInteger V257 = new BigInteger(257);
byte[] exp = new byte[256];
for (int idx = 0; idx < 256; ++idx)
  exp[idx] = BigInteger.ModPow(V45, new BigInteger(idx), V257) % 256;
byte[] log = new byte[256];
for (int idx = 0; idx < 256; ++idx)
  log[exp[idx]] = idx;

たとえば、このセットアップでログ45(131) = log[131] = 63、および4538 = exp[38] = 59.

(私はc#を書いたことがありません;私はただから推測しています BigInteger ドキュメンテーション;データ型にはエラーが発生する可能性があります。)

他のヒント

バイト値(0〜255)があり、ログベース45を取得し、別のバイトに保存したいですか?他の人が言ったように、あなたはそれをする際にある程度の正確さを失うでしょう。しかし、あなた できる 単にキャストするよりもうまくいく double 結果として byte.

255のログベース45は約1.455675です。一定の要因を掛けることにより、精度をある程度失って、バイトに保存できます。一定の要因は何ですか? 100を使用できます。これにより、145の値が得られますが、バイトのほぼ半分の範囲を失っています。表現したい最大の値は1.455675であるため、一定の乗数を使用できます 255/log45(255), 、または約175.176。

これはどれだけうまく機能しますか?どれどれ ...

        var mult = 255.0 / Math.Log(255, 45);
        Console.WriteLine("Scaling factor is {0}", mult);
        double errMax = double.MinValue;
        double errMin = double.MaxValue;
        double errTot = 0;
        for (int i = 1; i < 256; ++i)
        {
            // Get the log of the number you want
            var l = Math.Log(i, 45);

            // Convert to byte
            var b = (byte)(l * mult);

            // Now go back the other way.
            var a = Math.Pow(45, (double)b / mult);

            var err = (double)(i - a) / i;
            errTot += err;
            errMax = Math.Max(errMax, err);
            errMin = Math.Min(errMin, err);
            Console.WriteLine("{0,3:N0}, {1,3:N0}, {2}, {3:P4}", i, b, a, err);
        }
        Console.WriteLine("max error = {0:P4}", errMax);
        Console.WriteLine("min error = {0:P4}", errMin);
        Console.WriteLine("avg error = {0:P4}", errTot / 255);

私のマシンの.NET 4の下では、最大誤差は2.1419%、平均誤差は1.0501%です。

結果を丸めて平均エラーを減らすことができます Math.Pow. 。あれは:

var a = Math.Round(Math.Pow(45, (double)b / mult));

これにより、平均誤差が0.9300%に減少しますが、最大誤差は3.8462%に増加します。

コードを表示するのに役立つかもしれませんが、結果を保存することからあなたの問題は発生していると思います。

非整数番号を保存したい場合は、それをバイトに入れたくありません。代わりに、結果をダブルまたはより適切なものに保存します。

double result = math.log(154,45);

より安全な+が何であるかわからないので、この答えは役に立たないかもしれませんが、うまくいけば正しい方向に向けられるはずです。

これは実際には答えではありませんが、この質問を見ているユーザーのほんの一部は、おそらく double aに入力します byte[] タイプ。できることは単純です:

double theDouble = 78.24435;
byte[] theResult = BitConverter.GetBytes(theDouble);

byte[] theByteArray = new byte[]{0, 4, 2, 3}; //for example
double theCorrespondingDouble = BitConverter.ToDouble(theByteArray);

これはを使用します BitConverter .NET Initialyに存在すると思われるクラス。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top