0

人々がすでに発明したチェックサムアルゴリズムを使用する方が常に良いことを私は知っています。チェックサムを実行して、2つのファイルが同じであるかどうかを比較できるようにしたいと思います。ファイルはネットワーク上の2つの異なるコンピューターにあり、ネットワーク上にあるため、私の場合のように大きなファイルを処理する場合は、ファイル全体をコピーするよりもチェックサムを実行する方が高速です。(最初に、ファイルの長さが同じであることを確認するなど、他のテストを実行します。)

だから私はこの単純なアルゴリズムを作成しました:

private static double GetChecksum2(string file)
    {
        double checkSum = 0;

        var stream = File.OpenRead(file);

        // the bigger the chunck size the faster but the more memory usage by cpu
        // also when sending file over network it should not be that much more efficient

        int chunckSize = (int) Math.Pow(2,20); // 10 => kilobite   20 => megabite  30 => gigabite etc..
        byte[] buffer = new byte[chunckSize];

        int bytesRead = 0;

        while ( // while bytesRead > 0
            (bytesRead =
                (stream.Read(buffer, 0, buffer.Length)) // returns the number of bytes read or 0 if no bytes read
            ) > 0)
        {
            //buffer is now an array of size bytesRead

            // write those bytes to a file, perform checksum of file
            // etc...


            // temp check sum use a better algorithm I dont know if other computers will round 
            // doubles diferently

            for (int i = 0; i < bytesRead; i++)
            {
                checkSum = (((buffer[i] + i)/2 + checkSum))*.45;
            }


            //SHA256Managed sha = new SHA256Managed();
            //byte[] checksum = sha.ComputeHash(buffer);

        }

        return checkSum;
    }

このアルゴリズムを使用して、2つの異なるファイルのチェックサムが実現する確率はわかりません。

1.06 GBのファイルのチェックサムを実行する場合、次の時間がかかります。完了するまでに5.2秒かかり、チェックサムは321840.207306214になります。

代わりにSHA256Managed()アルゴリズムを使用すると、35.8秒かかります。

7倍長い

このアルゴリズムで同じチェックサムを持つ2つのファイルのオッズが異なることは、私のアルゴリズムよりもはるかに低いことを私は知っています。しかし、私のアルゴリズムを使用する方がはるかに高速であり、オッズもかなり低くなるはずです...

あるいは、私が知らない、すでに存在しているさらに高速なアルゴリズムを使用する必要があるかもしれません...

編集

私の質問は:

このアルゴリズムを実装しても安全ですか。ネットワークを介して多くのファイル転送を行う必要があります。チェックサムアルゴリズムを使用してファイルを比較できると便利です。たぶん、各ファイルをチャンクに分割して、チェックサムが一致しないチャンクを置き換えることができます!

4

2 に答える 2

3

浮動小数点演算は非決定論的です。.netのコンピューターまたはバージョンが異なると、結果がわずかに異なる場合があります。イプシロン比較で回避できるアルゴリズムでは、しかし多くのアルゴリズムではまったく回避できません。

アルゴリズムのもう1つの問題は、初期バイトの寄与が指数関数的に小さくなることです。つまり、ファイルの最後の部分だけがハッシュに影響を与えます。簡単な見積もりでは、最後の数kBのみが考慮されます。これは、ハッシュがその目的に適合しないことを意味します。

丸め誤差を無視すると、数式を簡略化できます。

(((buffer[i] + i)/2 + checkSum))*.45

buffer[i]*0.45/2 + i*0.45/2 + checkSum*0.45

再帰を解くと、次のようになります。

Sum(buffer[i]/2*(0.45^(length-1)) + i*(0.45^(length-1)))

2番目の項は長さにのみ依存するため、同じ長さのファイルを比較すると、次のようになります。

Sum(buffer[i]/2*(0.45^(length-1)))
于 2011-12-05T19:41:20.777 に答える
1

チェックサムにを使用するdoubleと、浮動小数点の問題が発生しやすくなります。それは本当に悪い考えだと思います。また、車輪の再発明も悪い決断だと思います。再利用できるチェックサム アルゴリズムは多数あります。

また、いくつかの関連する質問:

于 2011-12-05T19:39:21.587 に答える