为什么相同的位集不转换为相同的乌龙

why don't identical bitsets convert to identical ulong

本文关键字:转换 为什么      更新时间:2023-10-16

我正在处理std::bitset<16>向量中的数据,我都必须使用自制函数将其与无符号长(通过std::bitset::to_ulong())和字符串相互转换(确切的算法与这个问题无关)

Bitset 向量和字符串之间的转换起初似乎工作正常,因为如果我首先将位集向量转换为字符串,然后再转换回 bitset,它是相同的;我已经通过制作一个包含以下内容的程序来证明这一点:

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

由此判断,转换前后的位集显然是相同的,但是尽管如此,当我告诉它们转换为无符号长时,位集的转换完全不同;在一个可能看起来像这样的程序中:

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

首先,很明显,超出所有合理怀疑的位集在显示为二进制时是相同的,但是当转换为无符号长整型时,相同的位集返回完全不同的值(完全毁了我的程序)

这是为什么呢? 难道位集是单一的,即使它们打印为相同? 尽管位集相同,但与字符串转换器之间的位集中是否存在错误?

编辑:并非所有程序,包括我的对话都有这个问题,它只发生在我在创建位集(从字符串)后修改了位集时,在我的情况下,试图加密位集,这根本不能简化为简单而简短的东西,但在我最压缩的写作方式中,它看起来像这样:

(即使不包括公钥结构和模块化电源功能的定义)

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)不转换为相同的无符号长整型。

其他编辑:我还必须指出,无符号长整型的第一个打印值是"正确的",因为它们在使用时允许我完美地解密位集,而之后打印的无符号长整型的值是"错误的",因为它会产生完全错误的结果。

"11841744"值在较低的 16 位中是正确的,但在第 16 位以上有一些额外的设置位。这可能是 STL 实现中的一个错误,其中to_long访问的位超过它应该使用的 16 位。

或者(从上面的评论中)您向位集添加的位数超过了它可以容纳的位,并且您遇到了未定义的行为。

相关文章: