Search code examples
c++type-conversionbitset

why don't identical bitsets convert to identical ulong


I am dealing with data in a vector of std::bitset<16>, which i both have to convert to and from unsigned long (through std::bitset::to_ulong()) and to and from strings using a self-made function (the exact algorithm is irrelavant for this question)

the convertions between bitset vector and string does at first seem to work fine, since that if i first convert a vector of bitsets to string and then back to bitset it is identical; which i have proven by making a program which includes this:

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

the output could look somewhat like this (in this case with only 4 bitsets):

1011000011010000
1001010000011011
1110100001101111
1001000011001111

1011000011010000
1001010000011011
1110100001101111
1001000011001111

Judging by this, the bitsets before and after conversion are clearly identical, however despite this, the bitsets converts completely differently when i tell them to convert to unsigned long; in a program which could look like this:

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

the output could look somewhat like this:

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

firstly it is obvious that the bitsets still beyond all reasonable doubt are identical when displayed as binary, but when converted to unsigned long, the identical bitsets return completely different values (completely ruining my program)

Why is this? can it be that the bitsets are unidentical, even though they print as the same? can the error exist within my bitset to and from string converters, despite the bitsets being identical?

edit: not all programs including my conversations has this problem, it only happens when i have modified the bitset after creating it (from a string), in my case in an attempt to encrypt the bitset, which simply can not be cut down to something simple and short, but in my most compressed way of writing it looks like this:

(and that is even without including the defintion of the public key struct and the modular power function)

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;
}

I am well aware that you now all are thinking that i am doing the modular power function wrong (which i guarantee that i am not), but what i am doing to make this happen doesn't actually matter, for my question was not: what is wrong in my program; my question was: why don't the identical bitsets (which prints identical binary 1's and 0's) convert to identical unsigned longs.

other edit: i must also point out that the first printet values of unsigned longs are "correct" in that they when used allow me to decrypt the bitset perfectly, whereas the values of unsigned longs printed afterwards is "wrong" in that it produces a completely wrong result.


Solution

  • The "11841744" value is correct in the lower 16 bits, but has some extra set bits above the 16th. This could be a bug in your STL implementation where to_long accesses bits past the 16 it should be using.

    Or (from your comment above) you're adding more bits to the bitset than it can hold and you're experiencing Undefined Behavior.