0

私は現在、2進数を8進数に変換する基本的なプログラムに取り組んでいます。そのタスクは、0から256までのすべての数値を、2進数、8進数、および16進数に相当するものとともに表を印刷することです。このタスクでは、自分のコードを使用するだけで済みます(つまり、組み込み関数ではなく、ループなどを使用します)。私が作成したコード(現時点ではかなり厄介です)は次のとおりです(これはほんの一部です):

        int counter = ceil(log10(fabs(binaryValue)+1));
        int iter;
        if (counter%3 == 0)
        {
            iter = counter/3;
        }
        else if (counter%3 != 0)
        {
            iter = ceil((counter/3)); 
        }
        c = binaryValue;
        for (int h = 0; h < iter; h++)
        {
            tempOctal = c%1000;
            c /= 1000;
            int count = ceil(log10(fabs(tempOctal)+1));
            for (int counter = 0; counter < count; counter++)
            {
                if (tempOctal%10 != 0)
                {
                   e = pow(2.0, counter);
                   tempDecimal += e;
                }
                tempOctal /= 10;
            }
            octalValue += (tempDecimal * pow(10.0, h));
        }

出力は完全に間違っています。たとえば、バイナリコードが1111(10進値15)の場合、7が出力されます。これが発生する理由は理解できます(2進数の最後の3桁である111は10進形式では7です)が、できません。コード内の問題を特定します。何か案は?

編集:いくつかのデバッグとテストの後、私は答えを見つけました。

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    while (true)
{
    int binaryValue, c, tempOctal, tempDecimal, octalValue = 0, e;
    cout << "Enter a binary number to convert to octal: ";
    cin >> binaryValue;
    int counter = ceil(log10(binaryValue+1));
    cout << "Counter " << counter << endl;
    int iter;
    if (counter%3 == 0)
    {
       iter = counter/3;
    }
    else if (counter%3 != 0)
    {
       iter = (counter/3)+1; 
    }
    cout << "Iterations " << iter << endl;
    c = binaryValue;
    cout << "C " << c << endl;
    for (int h = 0; h < iter; h++)
    {
        tempOctal = c%1000;
        cout << "3 digit binary part " << tempOctal << endl;
        int count = ceil(log10(tempOctal+1));
        cout << "Digits " << count << endl;
        tempDecimal = 0;
        for (int counterr = 0; counterr < count; counterr++)
        {
            if (tempOctal%10 != 0)
            {
                 e = pow(2.0, counterr);
                 tempDecimal += e;
                 cout << "Temp Decimal value 0-7 " << tempDecimal << endl;
            }
            tempOctal /= 10;
        }
        octalValue += (tempDecimal * pow(10.0, h));
        cout << "Octal Value " << octalValue << endl;
        c /= 1000;
    }
cout << "Final Octal Value: " << octalValue << endl;
}
system("pause");
return 0;

}

4

5 に答える 5

2

これは非常に複雑に見えます。浮動小数点演算を使用する必要はなく、おそらく問題が発生する可能性があります。

もちろん、明らかな解決策は、これを行うために既存の関数を使用することです(同様{ char buf[32]; snprintf(buf, sizeof buf, "%o", binaryValue); }に実行されますが、本当に「手動」で実行したい場合は、ビット演算の使用を検討する必要があります。

  • binaryValue & 3最下位3ビットをマスクするために使用します。これらは次の8進数になります(3ビットは0..7、つまり1つの8進数です)。
  • binaryValue >>= 3数値をシフトして、3つの新しいビットを最下位に配置するために使用します
  • その後、数値を逆にするか、(可能であれば)文字列バッファの末尾から開始して、数字を逆方向に出力します
于 2011-07-07T08:27:44.140 に答える
1

あなたのコードを理解していません。複雑すぎるようです。しかし、1 つ確かなことは、内部表現を 8 進数に変換する場合、どこかで 8 で割り、どこかで a を行う必要があるということ% 8 です。そして、私はそれらを見ません。一方、10 と 1000 の両方で両方の操作が表示されますが、どちらも存在しないはずです。

unsigned手始めに、任意の基数を使用して、値 (できれば何らかの型unsigned の 。符号を気にする前に取得する) を文字列に変換する単純な関数を作成することをお勧めします。たとえば、次のようになります。

//! \pre
//!     base >= 2 && base < 36
//!
//! Digits are 0-9, then A-Z.
std::string convert(unsigned value, unsigned base);

これには、約 5 ~ 6 行のコードしか必要ありません。ただし、通常のアルゴリズムは逆の順序で数字を生成することに注意してstd::stringください。それ以外の場合: C スタイルは、十分に大きくすればうまく機能します。(符号付きでも、最後に a があっても、文字列を返す場合は必要ありません。) へのポインターを初期化し、数字を挿入するたびに事前にデクリメントするだけです。返す文字列を構築するには: トリックを行う必要があります。push_backstd::reversechar[]sizeof(unsigned) * CHAR_BITS + 2'\0'buffer + sizeof(buffer)std::string( pointer, buffer + sizeof(buffer) )

ループに関しては、終了条件は単にvalue == 0. (毎回で除算valueするので、この条件に到達することが保証されます。)だけでなく ,を使用すると、出力で少なくとも 1 桁が保証されます。basedo ... whilewhile

(コードを投稿するだけの方がはるかに簡単だったでしょうが、これは明らかに宿題なので、何をする必要があるかを示すだけの方がよいと思います。)

編集:実装を追加し、新しいコードにいくつかのコメントを追加しました:

最初のコメント: 非常に誤解を招くプロンプトがあります。に読み込む場合int、入力値は 10 進数にする必要があります。そして、私が理解していないことはまだあります% 1000。何をしていても、 と がないと正しくありません。試してみてください:たとえば、inputを実行して、何が得られるかを確認してください。/ 1000% 10/ 10% 8/ 8"128"

バイナリを入力しようとしている場合は、文字列を入力して自分で解析する必要があります。

変換自体の私のコードは次のようになります。

//! \pre
//!     base >= 2 && base <= 36
//!
//! Digits are 0-9, then A-Z.
std::string toString( unsigned value, unsigned base )
{
    assert( base >= 2 && base <= 36 );
    static char const digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    char buffer[sizeof(unsigned) * CHAR_BIT];
    char* dst = buffer + sizeof(buffer);
    do
    {
        *--dst = digits[value % base];
        value /= base;
    } while (value != 0);
    return std::string(dst, buffer + sizeof(buffer));
}

入力を解析したい場合 (バイナリなど)、次のような方法でうまくいくはずです:

unsigned fromString( std::string const& value, unsigned base )
{
    assert( base >= 2 && base <= 36 );
    static char const digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    unsigned results = 0;
    for (std::string::const_iterator iter = value.begin();
            iter != value.end();
            ++ iter)
    {
        unsigned digit = std::find
            ( digits, digits + sizeof(digits) - 1,
              toupper(static_cast<unsigned char>( *iter ) ) ) - digits;
        if ( digit >= base )
            throw std::runtime_error( "Illegal character" );
        if ( results >= UINT_MAX / base
             && (results > UINT_MAX / base || digit > UINT_MAX % base) )
            throw std::runtime_error( "Overflow" );
        results = base * results + digit;
    }
    return results;
}

toString考えられるあらゆる種類のエラー状態を処理する必要があるため、より複雑です。また、おそらく必要以上に単純です。おそらく、空白などもトリミングしたいでしょう(またはそれらを無視することさえできます:入力01000000は よりもエラーが発生しやすいです0100 0000)。

(また、コンパイラが末尾 に を挿入するため、 の終了イテレータにfindは があります。)- 1'\0'digits

于 2011-07-07T08:55:20.757 に答える
0
#include <cmath>
#include <iostream>
#include <string>
#include <cstring>
#include <cctype>
#include <cstdlib>

using namespace std;

char*  toBinary(char* doubleDigit)
{
  int digit = atoi(doubleDigit);
  char* binary = new char();

  int x = 0 ;
  binary[x]='(';
  //int tempDigit = digit;
 int k=1;
  for(int i = 9 ; digit != 0; i--)
  {
    k=1;//cout << digit << endl;
    //cout << "i"<< i<<endl;
    if(digit-k *pow(8,i)>=0)
    {


      k =1;
      cout << "i" << i << endl;
      cout << k*pow(8,i)<< endl;

      while((k*pow(8,i)<=digit))
      {
    //cout << k <<endl;
    k++;
      }
      k= k-1;



       digit = digit -k*pow(8,i);

      binary[x+1]= k+'0';
      binary[x+2]= '*';
      binary[x+3]= '8';
      binary[x+4]='^';
      binary[x+5]=i+'0';
      binary[x+6]='+';

    x+=6;

    }

  }
  binary[x]=')';
  return binary;
}

int main()
{
 char value[6]={'4','0','9','8','7','9'};



 cout<< toBinary(value); 



  return 0 ;
}
于 2012-10-14T21:52:12.467 に答える
0

実際、必要なことを達成するためになぜそれほど複雑なコードが必要なのか理解できません。

まず、2進数から8進数への変換などはありません 10進数への変換や10進数からの変換なども同様です)。マシンは常にバイナリで動作します。これについてできること(またはすべきこと)はありません。

これは実際にはフォーマットの問題です。つまり、数値を8進数として印刷する方法と、8進数のテキスト表現を解析する方法です。

編集:

次のコードを使用して、任意の基数で数値を印刷できます。

const int PRINT_NUM_TXT_MAX = 33; // worst-case for binary

void PrintNumberInBase(unsigned int val, int base, PSTR szBuf)
{
    // calculate the number of digits
    int digits = 0;
    for (unsigned int x = val; x; digits++)
        x /= base;

    if (digits < 1)
        digits = 1; // will emit zero

    // Print the value from right to left

    szBuf[digits] = 0; // zero-term

    while (digits--)
    {
        int dig = val % base;
        val /= base;

        char ch = (dig <= 9) ?
            ('0' + dig) :
            ('a' + dig - 0xa);

        szBuf[digits] = ch;
    }
}

例:

char sz[PRINT_NUM_TXT_MAX];
PrintNumberInBase(19, 8, sz);
于 2011-07-07T08:32:23.727 に答える
0

OP が生成を求めているコードは、別の基数の数値が必要な場合に関数電卓が行うことです。

あなたのアルゴリズムは間違っていると思います。ざっと見てみると、端に向かって二乗されている関数が見えます。なぜ?あなたが話していることを行う簡単な数学的方法があります。数学部分を取得したら、それをコードに変換できます。

鉛筆と紙があり、計算機がない場合 (事前に作成された関数を使用しない場合と同様)、現在の基数を取得し、基数 10 に変更してから、必要な基数に変更します。あなたの場合、それは基数 8、基数 10、基数 2 になります。

これで始められるはずです。本当に必要なのは、剰余を取得するためのモジュラスを含む if/else ステートメントだけです。 http://www.purplemath.com/modules/numbbase3.htm

次に、目的の出力を取得する方法を理解する必要があります。たぶん、残りを配列に保存するか、txtファイルに出力します。

(このような問題については、私が応用数学で専攻を 2 倍にしたい理由です)

10 進数の 0 から 256 までの変換が必要なため、int binary()、char hex()、int octal() などの関数を作成するのが最も簡単です。2 進数と 8 進数は整数でしか表現できないため、最初に行うのが最も簡単です。

于 2011-07-07T08:59:42.117 に答える