0

我编写了一个将十进制数转换为二进制数的函数。我输入我的十进制数作为long long int. 它适用于小数字,但我的任务是确定计算机如何处理溢出,因此当我输入 (2^63) - 1 时,函数输出十进制值为 9223372036854775808 并且在二进制中它等于 -954437177。当我输入 2^63 这是一个 64 位机器无法保存的值时,我收到警告说整数常量太大以至于它是无符号的,并且十进制常量仅在 ISO C90 和十进制的输出中是无符号的值为负 2^63,二进制数为 0。我使用 gcc 作为编译器。这个结果正确吗?

代码如下:

#include <iostream>
#include<sstream>
using namespace std;
int main()
{
long long int answer;
long long dec;
string binNum;
stringstream ss;
cout<<"Enter the decimal to be converted:"<< endl;;
cin>>dec;
cout<<"The dec number is: "<<dec<<endl;
while(dec>0)
{
     answer = dec%2;
     dec=dec/2;
     ss<<answer;
     binNum=ss.str();
}
cout<<"The binary of the given number is: ";
for (int i=sizeof(binNum);i>=0;i--){
     cout<<binNum[i];}
return 0;
    }
4

2 回答 2

7

首先,“在 64 位计算机上”毫无意义:long long无论计算机如何,都保证至少 64 位。如果可以将现代 C++ 编译器压在 Commodore 64 或 Sinclair ZX80 上,或者就此而言是 KIM-1,along long仍然至少是 64 位。这是C++ 标准给出的与机器无关的保证。

其次,指定过大的值“溢出”不同。

使这个问题有点有趣的唯一一点是存在差异。并且该标准对这两种情况的处理方式不同。对于使用整数值初始化有符号整数的情况,如有必要,将执行转换,如果无法表示该值,则具有实现定义的效果,……

C++11 §4.7/3:“如果目标类型是有符号的,如果它可以在目标类型(和位域宽度)中表示,则值不变;否则,该值是实现定义的”

而对于例如产生无法由参数类型表示的值的乘法的情况,效果是未定义的(例如,甚至可能崩溃)......

C++11 §5/4:“如果在计算表达式期间,结果未在数学上定义或不在其类型的可表示值范围内,则行为未定义。”

关于代码II是在写完上面之后才发现的,但看起来它确实会产生足够大的溢出(即未定义行为)。将您的数字放在 avectorstring中。请注意,您也可以只使用 abitset来显示二进制数字。

哦,KIM-1。很多人不知道,所以放一张照片:

KIM-1单板机

据报道,它非常好,尽管键盘有些受限。

于 2012-09-09T23:35:13.090 回答
1

您的代码的这种改编会产生您需要的答案。您的代码很容易产生错误顺序的位的答案。对十进制值 123、1234567890、12345678901234567 的详尽测试表明它工作正常(Mac OS X 10.7.4 上的 G++ 4.7.1)。

#include <iostream>
#include<sstream>
using namespace std;
int main()
{
    long long int answer;
    long long dec;
    string binNum;
    cout<<"Enter the decimal to be converted:"<< endl;;
    cin>>dec;
    cout<<"The dec number is: "<<dec<<endl;
    while(dec>0)
    {
        stringstream ss;
        answer = dec%2;
        dec=dec/2;
        ss<<answer;
        binNum.insert(0, ss.str());
//      cout << "ss<<" << ss.str() << ">>   bn<<" << binNum.c_str() << ">>" << endl;
    }
    cout<<"The binary of the given number is: " << binNum.c_str() << endl;

    return 0;
}

测试运行:

$ ./bd
Enter the decimal to be converted:
123
The dec number is: 123
The binary of the given number is: 1111011
$ ./bd
Enter the decimal to be converted:
1234567890
The dec number is: 1234567890
The binary of the given number is: 1001001100101100000001011010010
$ ./bd
Enter the decimal to be converted:
12345678901234567
The dec number is: 12345678901234567
The binary of the given number is: 101011110111000101010001011101011010110100101110000111
$ bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
obase=2
123
1111011
1234567890
1001001100101100000001011010010
12345678901234567
101011110111000101010001011101011010110100101110000111
$

当我用 64 位机器可能的最大值编译它时,我的二进制值没有任何显示。

$ bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
2^63-1
9223372036854775807
quit
$ ./bd
Enter the decimal to be converted:
9223372036854775807
The dec number is: 9223372036854775807
The binary of the given number is: 111111111111111111111111111111111111111111111111111111111111111
$

如果您为可以表示的最大值选择更大的值,则所有赌注都关闭;你可能会得到一个 0cin >> dec;并且代码不能正确处理 0。


序幕

问题中的原始代码是:

#include <iostream>
using namespace std;
int main()
{
    int rem,i=1,sum=0;
    long long int dec = 9223372036854775808; // = 2^63     9223372036854775807 =  2^63-1
    cout<<"The dec number is"<<dec<<endl;
    while(dec>0)
    {
        rem=dec%2;
        sum=sum + (i*rem);
        dec=dec/2;
        i=i*10;
    }
    cout<<"The binary of the given number is:"<<sum<<endl;
    return 0;
}

我对前面的代码给出了这样的分析:

对于 64 位数字中的每个位位置,您将普通int变量乘以 10。i鉴于这i可能是一个 32 位的数量,您会遇到有符号整数溢出,这是未定义的行为。即使i是 128 位的量,也不足以准确处理所有可能的 64 位数字(例如 2 63 -1)。

于 2012-09-09T23:34:18.207 回答