2009-12-22 11 views
9
Ben aşağıdaki özelliklere sahip bir Perl dize sağlama fonksiyonu arıyorum

:0..2^32-1 aralığında Perl üreten değerlerinde hızlı bir dize sağlama işlevi

  • Girdi: tanımsız Unicode dizesi uzunluğu ($string)
  • Çıkış: işaretsiz bir tamsayı ($hash), 0 <= $hash <= 2^32-1 sahip olduğu için

Pseudo-kodu (0 4 baytlık MySQL işaretsiz int boyutunu eşleşen 4294967295, üzere)

sub checksum { 
    my $string = shift; 
    my $hash; 
    ... checksum logic goes here ... 
    die unless ($hash >= 0); 
    die unless ($hash <= 4_294_967_295); 
    return $hash; 
} 

İdeal sağlama fonksiyonu çalıştırmak için hızlı olmalı ve hemen hemen eşit çakışmaları önlemek için hedef alanı (0 .. 2^32-1) değerleri üretmelidir. Bu uygulamada rastgele çarpışmalar tamamen ölümcül değildir, fakat açıkçası onları mümkün olduğu ölçüde engellemek istiyorum.

Bu gereksinimler verildiğinde, bunu çözmenin en iyi yolu nedir?

+0

sindirir? Tamsayı neden önemlidir? Sindirimi bir ip olarak saklamak zorunda kalsanız bile, MD5 gibi bir şeyi kullanmayla ne dersiniz? –

+1

"Tüm olası dizelerle çarpışmalardan kaçınmak istiyorsunuz" - Hayır, soruda belirtildiği gibi "mümkün olduğu ölçüde onları önlemek istiyorum". – knorv

+0

"Neden bir tamsayı kullanıyor?" - Soruda belirtildiği gibi, sağlama toplamı "4 byte MySQL imzasız int" olarak saklanır. – knorv

cevap

11

Herhangi bir karma işlevi yeterli olacaktır - sadece 4 baytlık bir kısma böler ve bir sayıya dönüşür. İyi karma fonksiyonları rasgele bir dağılıma sahiptir ve dizgeyi nerede kırptığınız önemli değil, bu dağılım sabit olacaktır.

Digest::MD5'u öneririm çünkü standart olarak Perl ile gelen en hızlı karma uygulamasıdır. String :: CRC, Pim'in de belirttiği gibi, C de uygulanır ve daha hızlı olmalıdır.

use Digest::MD5 qw(md5); 
my $str = substr(md5("String-to-hash"), 0, 4); 
print unpack('L', $str); # Convert to 4-byte integer (long) 
+1

B :: hash ayrıca core perl ile birlikte gelir, internal core hash işlevini kullanır, MD5'ten daha hızlıdır ve bir hexified 32 bit tam sayı döndürür. Ama MD5 kadar güvenli değil. – rurban

4

Ne kadar hızlı olduğunu bilmiyorsunuz, ancak String::CRC'u deneyebilirsiniz.

3

perldoc -f unpack: From:

Burada karma hesaplayıp tam sayıya dönüştürmek nasıl

Tüm olası dizeleri ile çarpışmaları önlemek, ama sadece 4 milyar mümkün olmasını istediğiniz
 For example, the following computes the same number as the 
     System V sum program: 

      $checksum = do { 
       local $/; # slurp! 
       unpack("%32W*",<>) % 65535; 
      }; 
+0

Tüm bitlerin bu 32 bit toplamı, rasgele dağılımlar için çok kötü bir karma değerdir. Herhangi bir karma işlevi en basit olanları bile daha iyidir. – rurban

+0

Elbette, ama System V' sum' programının sahip olduğu aynı sorun. Paragraf bakın. Yoksa "toplam" ın tartışmalı bir şekilde kırıldığını mı düşünüyorsun? Bu durumda Perl ile ilgili değil. –

+0

'toplamı, yukarıda belirtildiği gibi, olabildiğince hızlı olmakla birlikte, aşırı derecede sağlam değildir. Boyutu kullanarak, örneğin, biraz '$ _ = <>; paketini açınız ("% 32W *", $ _)% 65535. uzunluğu ($ _) '. Daha sağlam olması gereken herhangi bir şey 'Digest :: MD5' veya Digest :: SHA' vb. –

İlgili konular