2012-05-28 21 views
3

我已經寫了一個c程序,該程序應該將文件切片爲Rabin Karp algorithm。這是一個c#程序的改編,你可以找到Here用rabin karp算法切片文件

它似乎工作,但問題依然存在。平均塊大小不是預期的。

用法如下:

拉賓總理WindowSize BoundaryMarker文件

其中:

拉賓是可執行文件的名稱。

總理是一個高素數。例如100007

WindowSize是滾動窗口的大小。例如48

BoundaryMarker處於指紋

文件設置爲0的比特的數目被處理

如果我設置BoundaryMarker至13的文件,我期望平均信息塊尺寸是8K。事實上,他們都不在8K左右。

我很難弄清楚我的程序出了什麼問題? 你能幫我嗎?

感謝

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <fcntl.h> 

unsigned char* buffer; 
int windowSize; 
int writePointer = 0; 
int readPointer = 0; 
int dataSize = 0; 

unsigned char PushChar(unsigned char c) 

{ if (++writePointer >= windowSize) writePointer=0; 
    buffer[writePointer]=c; 
    dataSize++; 
    return(c); 
} 

unsigned char PopChar(void) 

{ if (++readPointer >= windowSize) readPointer=0; 
    dataSize--; 
    return(buffer[readPointer]); 
} 


int main(int argc, char *argv[]) 

{ int fd; 
    unsigned char c; 

    unsigned long Q; 
    unsigned long D=256; 
    unsigned long pow=1; 
    int i,k,boundary,boundaryMarker,index; 
    unsigned char s; 

    if (argc != 5) 
    { printf("\nUsage : rabin Prime WindowSize BoundaryMarker File\n\nwhere :\n"); 
    printf("Prime is a high prime number. For instance 100007\n\n"); 
    printf("WindowSize is the size of rolling window. For instance 48\n\n"); 
    printf("BoundaryMarker is the number of bits set to 0 in a fingerprint\n\n"); 
    printf("File is the file to process\n\n"); 
    return(1); 
    } 

    sscanf(argv[1],"%lu",&Q); 
    sscanf(argv[2],"%d",&windowSize); 
    sscanf(argv[3],"%d",&boundaryMarker); 

    for(i=1,boundary=1;i<=boundaryMarker;i++) boundary=boundary*2; 
    boundary --; 

    //printf("Q = %lu windowSize = %d boundary = %d\n",Q,windowSize,boundary); 

    if ((buffer=(unsigned char*) malloc (sizeof(unsigned char)*windowSize))==NULL) return(1); 

    for (k=1; k < windowSize; k++) pow=(pow*D)%Q; 
    //printf("pow value %lu\n",pow); 

    unsigned long sig=0; 
    int lastIndex=0; 

    if ((fd=open(argv[4],O_RDONLY))<0) exit(1); 

    for (i=0; i <windowSize; i++) 
    { read(fd,&c,1); 
    PushChar(c); 
    sig=(sig*D + (unsigned long)c) %Q; 
    } 

    //printf("sig value = %lu\n",sig); 

    index=0; lastIndex=0; 

    while (read(fd,&c,1)) 
    { 
    s=PopChar(); 
    //printf("sig = (%lu + %lu - %lu * %lu %% %lu) %lu",sig,Q,pow,(unsigned long) s,Q,Q); 
    sig = (sig + Q - pow*(unsigned long)s%Q)%Q; 
    //printf(" = %lu\n",sig); 
    s=PushChar(c); 
    //printf("sig2 = (%lu * %lu + %lu) %% %lu",sig,D,(unsigned long) s,Q); 
    sig = (sig*D + (unsigned long)s)%Q; 
    //printf(" = %lu\n",sig); 
    index++; 
    if ((sig & boundary)==0) 
     { if (index - lastIndex >= 2048) 
     { printf("sig & boundary = %lu & %lu Index=%d chunk size=%d\n",sig,boundary,index,index-lastIndex); 
      lastIndex=index; 
    } 
     } 
    else if (index -lastIndex >=65536) 
      { printf("sig & boundary = %lu & %lu Index=%d chunk size=%d\n",sig,boundary,index,index-lastIndex); 
       lastIndex=index; 
      } 
    } 
    printf("Index=%d chunk size=%d\n",index,index-lastIndex); 

    close(fd); 
    return 1; 
} 
+0

可以通過步帶調試器的代碼,並關注變量及其值。它可能會幫助您找出問題所在。 –

+0

這兩個程序(c和c#都給出了相同的結果)。我認爲這是一個算法問題。該算法看起來像sedgewick rabin karp實現。我不知道問題出在哪裏。 –

回答

-1

你可以嘗試更新BoundaryMarker值,就可以得到不同的長度。我以這種方式使用RB:github link。我認爲長度實際上依賴於內容。

1

在兆字節的隨機數據上運行BoundaryMarker = 13的代碼給了我104個塊,平均塊大小爲10082字節。這與預期的8192相差不遠。

但是,較小的BoundaryMarker值顯示更明顯的偏差;例如,將它設置爲10,給我的平均塊大小爲3049字節,與期望的1024相差甚遠。並且設置BoundaryMarker = 5產生的平均塊大小爲2077字節,甚至沒有任何地方附近預期大小爲32字節。

在你的代碼更仔細地觀察,這種偏見的明顯的原因是在下面的代碼(重新格式化爲清晰起見):

if ((sig & boundary) == 0) 
{ if (index - lastIndex >= 2048) 
    { printf("sig & boundary = %lu & %lu Index=%d chunk size=%d\n",sig,boundary,index,index-lastIndex); 
    lastIndex=index; 
    } 
} 
else if (index - lastIndex >= 65536) 
{ printf("sig & boundary = %lu & %lu Index=%d chunk size=%d\n",sig,boundary,index,index-lastIndex); 
    lastIndex=index; 
} 

if (index - lastIndex >= 2048)抑制塊邊界是從以前的邊界小於2048個字節,有效地將小於2048字節的塊與下面的塊合併在一起。 else if (index - lastIndex >= 65536)檢查,同時,強制人爲塊邊界,以防止任何塊增長超過65536字節。

如果這種行爲(這會強制所有塊至少爲2048和65536個大部分字節長)是不是你想要的,你可以簡單地刪除那些檢查,簡化了代碼是什麼,只是:

if ((sig & boundary) == 0) 
{ printf("sig & boundary = %lu & %lu Index=%d chunk size=%d\n",sig,boundary,index,index-lastIndex); 
    lastIndex=index; 
} 

實際上,使這種改變得到的平均信息塊尺寸非常接近2個ñ字節BoundaryMarker = ñ,至少對於ñ ≤ 12左右。

對於Ñ = 13,似乎是顯着的向下偏壓,這是我懷疑的事實,所述原100007僅爲約12.2倍的邊界模量2 引起。由於簽名值或多或少地隨機分佈在素數模上,當進一步減少模2 時,額外的0.2導致它們略微偏向較小的值(包括零)。

該偏置可以通過使用一個更大的質容易地固定,如2- − 1 = 2147483647實際上,切換到此素使得平均信息塊尺寸更接近8192