2016-11-29 4 views
2

std::bitset<16>のベクトルのデータを処理しています。これは、符号なしlongから(符号なしstd::bitset::to_ulong()を介して)変換する必要があります。 (正確なアルゴリズムはこの質問には関係ありません)なぜ同じビットセットが同一のulongに変換されないのですか

ビットセットベクトルと文字列の変換は最初はうまくいくようですが、最初にビットセットのベクトルを文字列に変換してからビットセットに戻すと同じです。私はこの含むプログラムを作ることによって実証されていた:

for (std::bitset<16>& B : my_bitset16vector) std::cout<<B<<std::endl;//print bitsets before conversion 

bitset_to_string(my_bitset16vector,my_str); 
string_to_bitset(my_bitset16vector,my_str); 

std::cout<<std::endl 
for (std::bitset<16>& B : my_bitset16vector) std::cout<<B<<std::endl;//print bitsets after conversion 

出力は(唯一の4ビットセットで、この場合には)このように、多少なります:

1011000011010000 
1001010000011011 
1110100001101111 
1001000011001111 

1011000011010000 
1001010000011011 
1110100001101111 
1001000011001111 

ビットセットの前に、このによる判断変換後も明らかに同じですが、ビットセットは符号付きlongに変換するように指示すると完全に別の変換を行います。このようになります。プログラムで:

for (std::bitset<16>& B : my_bitset16vector) std::cout<<B<<".to_ulong()="<<B.to_ulong()<<std::endl;//print bitsets before conversation 

bitset_to_string(my_bitset16vector,my_str); 
string_to_bitset(my_bitset16vector,my_str); 

std::cout<<std::endl 
for (std::bitset<16>& B : my_bitset16vector) std::cout<<B<<".to_ulong()="<<B.to_ulong()<<std::endl;//print bitsets after conversion 

出力がやや次のようになります。

1011000011010000.to_ulong()=11841744 
1001010000011011.to_ulong()=1938459 
1110100001101111.to_ulong()=22472815 
1001000011001111.to_ulong()=18649295 

1011000011010000.to_ulong()=45264 
1001010000011011.to_ulong()=37915 
1110100001101111.to_ulong()=59503 
1001000011001111.to_ulong()=37071 

を第一に、のように表示する場合、すべての合理的な疑いをを超えた今でもビット集合が同一であることは明らかですバイナリですが、符号なしlongに変換すると、と同じビセットは完全に異なる値を返します(私のプログラムを完全に破壊します)

なぜですか彼の?ビットセットが同じものとして印刷されても、ビットセットが同じではないことがありますか?ビットセットがであるにもかかわらず、であるにもかかわらず、文字列変換器との間でビットセット内にエラーが存在する可能性がありますか?

編集:私の会話を含むすべてのプログラムがこの問題を抱えているわけではありません。私はビットセットを暗号化しようとして(文字列から)作成した後にのみ変更しますシンプルで短いものに削減しますが、書き込みの私の最も圧縮された方法でそれは次のようになります。

(そしてそれは、公開鍵構造体とモジュラー電源機能のdefintion含めなくてもです)

int main(int argc, char**argv) 
{ 
    if (argc != 3) 
    { 
     std::cout<<"only 2 arguments allowed: plaintext user"<<std::endl; 
     return 1; 
    } 

    unsigned long k=123456789;//any huge number loaded from an external file 
    unsigned long m=123456789;//any huge number loaded from an external file 


    std::vector< std::bitset<16> > data;  
    std::string datastring=std::string(argv[1]); 

    string_to_bitset(data,datastring);//string_to_bitset and bitset_to_string also empties string and bitset vector, this is not the cause of the problem 

    for (std::bitset<16>& C : data) 
    { 
     C =std::bitset<16>(modpow(C.to_ulong(),k,m));//repeated squaring to solve C.to_ulong()^k%m 
    } 

    //and now the problem happens  


    for (std::bitset<16>& C : data) std::cout<<C<<".to_ulong()="<<C.to_ullong()<<std::endl; 

    std::cout<<std::endl; 

    bitset_to_string(data,datastring); 
    string_to_bitset(data,datastring); 
    //bitset_to_string(data,datastring); 

    for (std::bitset<16>& C : data) std::cout<<C<<".to_ulong()="<<C.to_ullong()<<std::endl; 

    std::cout<<std::endl; 
return 0; 
} 

私はあなたが今私がモジュラーパワー機能を間違っていると思っていることをよく知っています私の問題ではないので、私のプログラムで何が間違っているのですか?私の質問は、なぜ同じビットセット(同一のバイナリ1と0を出力する)が同じunsigned longに変換されないのかということです。

他の編集:私はまた、署名されたロングの最初のプリントセットの値が "正しい"ことを指摘しておかなければなりません。それは完全に間違った結果を生むということです。

+0

この問題を複製する最小のコードを抽出してください(これを示す小さなメインなど)。ビットセットにどのようにデータを割り当てるかの例は見えません。 –

+2

どのコンパイラを使用していますか? "11841744"の値は下位16ビットでは正しいですが、16番より上には余分なビットがいくつかあります。これは、STL実装のバグで、to_longが使用するはずの16ビットを超えるビットにアクセスする場合があります。 – 1201ProgramAlarm

+0

あなたは私のケースでは@ 1201ProgramAlarmが正しいと思います。16ビットはすべてのデータを含む小さなものですが、私のコンパイラは16ビットから32ビットにアップグレードするとビットセットにすべてのデータを追加します。あなたが答えとしてあなたのコメントを投稿できるなら、私はそれを受け入れます – Nikolaj

答えて

1

"11841744"の値は下位16ビットで正しくありますが、16番より上には余分なビットがいくつかあります。これは、STL実装のバグで、to_longが使用するはずの16ビットを超えるビットにアクセスする場合があります。

(上記のコメントから)ビットセットに保持できるビット数を増やしていますが、未定義の動作が発生しています。

関連する問題