0

10 進数を 2 進数に変換する関数を作成しました。10 進数を として入力しlong long intます。小さい数値でも問題なく動作しますが、私の仕事はコンピューターがオーバーフローを処理する方法を決定することなので、(2^63) - 1 を入力すると、関数は 10 進数値が 9223372036854775808 であり、2 進数では -954437177 に等しいと出力します。64ビットマシンが保持できない値である2 ^ 63を入力すると、整数定数が大きすぎて符号なしであり、10進定数がISO C90でのみ符号なしであり、10進数の出力であるという警告が表示されます値は負の 2^63 で、2 進数は 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++ 標準によって与えられるマシンに依存しない保証です。

第二に、大きすぎる値を指定することは「オーバーフロー」と同じではありません。

この質問を少し興味深いものにしている唯一のことは、違いがあるということです。そして、標準ではこれら 2 つのケースを異なる方法で扱っています。符号付き整数を整数値で初期化する場合、必要に応じて変換が実行され、値を表すことができない場合は実装定義の効果があります。

C++11 §4.7/3 : 「宛先の型が署名されている場合、宛先の型 (およびビット フィールド幅) で表現できる場合、値は変更されません。それ以外の場合、値は実装定義です。」

一方、たとえば引数の型で表現できない値を生成する乗算の​​場合、その効果は未定義です (たとえば、クラッシュする可能性さえあります) …

C++11 §5/4 : 「式の評価中に、結果が数学的に定義されていないか、その型の表現可能な値の範囲内にない場合、動作は未定義です。」

コードについては、II が上記を書いて初めて発見しましたが、十分な数の場合、必ずオーバーフロー (未定義の動作) が発生するようです。vectorまたはに数字を入れますstringbitseta を使用して 2 進数を表示することもできることに注意してください。

ああ、KIM-1。あまり知られていないので、写真を載せておきます。

KIM-1 シングルボード コンピュータ

伝えられるところによると、キーボードは多少制限されていましたが、非常に良かったです。

于 2012-09-09T23:35:13.090 に答える
1

コードをこのように適応させると、必要な答えが得られます。あなたのコードは、ビットの順序が間違っている回答を生成する傾向があります。10 進数値 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
$

表現できる最大値に大きな値を選択すると、すべての賭けが無効になります。から 0 が返されることがありますがcin >> 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おそらく 32 ビットの量であるとすれiば、未定義の動作である符号付き整数のオーバーフローが発生しています。128 ビットの量であったとしても、可能なすべての 64 ビット数 (2 63 -1iなど) を正確に処理するには十分な大きさではありません。

于 2012-09-09T23:34:18.207 に答える