我正在尝试将二进制值转换为十六进制值,我得到以下代码,它可以很好地工作到28位但不是32位。
代码如下。
int main()
{
long int longint=0;
string buf;
cin>>buf;
int len=buf.size();
for(int i=0;i<len;i++)
{
longint+=( buf[len-i-1]-48) * pow((double)2,i);
}
cout<<setbase(16);
cout<<longint;
return 0;
}
如果输入28'1'(111111111111111111111111),则输出为fffffff 但如果我输入32'1'(11111111111111111111111111111111),则输出为80000000。
任何人都可以解释为什么会发生这种情况,也可以在上面的代码中解释为什么减去48。
答案 0 :(得分:1)
问题似乎是使用pow
,它使用浮点数学,如果我没记错的话。你可能遇到溢出问题。
计算2的幂的更优雅的方法是使用位移:
2^0 = 1 << 0 = 1
2^1 = 1 << 1 = 2
2^2 = 1 << 2 = 4
2^n = 1 << n
答案 1 :(得分:1)
作为Nathan的帖子,在更改代码时,它会显示正确,
longint += (buf[len-i-1]-'0') << i;
答案 2 :(得分:1)
您使用的是int32,当它用于32个字节时它超出范围,尝试使用int64即long long
unsigned long long longint=0; //Change Here
string buf;
cin>>buf;
int len=buf.length();
for(int i=0;i<len;i++)
{
longint+=( buf[len-i-1]-48) * pow((double)2,i);
}
cout<<setbase(16);
cout<<longint;
答案 3 :(得分:0)
这是因为您已强制将( buf[len-i-1]-48) * pow((double)2,i)
转换为双,
和 double 长度为8个字节,但它必须存储额外信息,因此无法完全充电以表示0x80000000,您可以找到更多信息{{ 3}}
和你的上一个( buf[len-i-1]-48) * pow((double)2,i)
(当我31岁时)表达已经溢出。
击>
但是当从4294967295.0000000(这是0xffffffff)转换为int时它会发生一些问题,它只是出现了0x80000000 ,但我很抱歉我不知道为什么(请参考TonyK的评论)。<登记/>
您可以将其更改为
longint + =(long int)((buf [len-i-1] -48)* pow(2,i));
为什么减48?
因为'0'的ascii是48,你想要从文字'0'转换为数字0,你必须这样做。
答案 4 :(得分:0)
原因是浮点值具有极限精度,而pow()计算机使用的数值计算近似值并不一定精确。要获得精确值,您应该使用逐位“&gt;&gt;”代替。
你可以看到pow()函数如何工作如下。
我改变了你的代码
longint + =(buf [len-i-1] -48)* pow((double)2,i)
到下面的代码,相等,因为pow()返回一个double值。
double temp = ( buf[len-i-1]-48) * pow((double)2,i);
longint+= temp;
cout<<setbase(16);
cout<<"temp"<<endl;
cout<<temp<<endl;
cout<<longint<<endl;
输出如下
temp
1.34218e+08
fffffff
temp
2.68435e+08
1fffffff
temp
5.36871e+08
3fffffff
temp
1.07374e+09
7fffffff
temp
2.14748e+09
80000000
final
80000000
其中显示pow()的精确度有限。 2.14748e+09
不等于(2 ^ 31)。
你应该使用“&gt;&gt;”这是最好的或只是使用转换为整数,也不是100%相关。
您可以看到如下转换。
当我改变时
double temp =(buf [len-i-1] -48)* pow((double)2,i);
到
int temp =(buf [len-i-1] -48)* pow((double)2,i);
结果是
temp
8000000
fffffff
temp
10000000
1fffffff
temp
20000000
3fffffff
temp
40000000
7fffffff
temp
80000000
ffffffff
final
ffffffff
哪种方法正常。
减去48 你从标准输入中得到一个字符,例如,你从终端得到'1'而不是1.为了得到1.你应该使用'1' - '0'。 原因是:计算机存储'0'~'9'作为一个具有值的字节(48~57)。结果,'1' - '0'等于'1' - 48。