使用C ++中的循环进行八进制转换

时间:2011-07-07 08:22:58

标签: c++ binary octal

我目前正在研究一个将二进制数转换为八进制数的基本程序。它的任务是打印一个表,其中所有数字都在0-256之间,其二进制,八进制和十六进制等效。该任务要求我只使用自己的代码(即使用循环等而不是内置函数)。我所制作的代码(目前非常混乱)如下(这只是一个snippit):

        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(十进制值15)时,它输出7.我可以理解为什么会发生这种情况(二进制数中的最后三位数,111,十进制格式为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;

}

5 个答案:

答案 0 :(得分:2)

这看起来过于复杂。没有必要涉及浮点数学,它很可能会引入问题。

当然,显而易见的解决方案是使用预先存在的函数来执行此操作(如{ char buf[32]; snprintf(buf, sizeof buf, "%o", binaryValue); }并完成,但如果您真的想“手动”执行此操作,则应考虑使用位-operations:

  • 使用binaryValue & 3屏蔽三个最低位。这些将是你的下一个八进制数字(三位是0..7,这是一个八进制数字)。
  • 使用binaryValue >>= 3来移动数字以使三个新位进入最低位置
  • 之后反转数字,或者(如果可能的话)从字符串缓冲区的末尾开始并向后发射数字

答案 1 :(得分:1)

它不理解你的代码;它似乎太复杂了。但是一个 事情是肯定的,如果你正在转换内部表示 八进制,你必须在某个地方除以8,然后做一个% 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,最简单的解决方案是push_back每个数字, 然后在返回之前调用std::reverse。否则:a C风格char[]效果很好,只要你足够大。 (sizeof(unsigned) * CHAR_BITS + 2绰绰有余,即使是 已签名,即使最后有'\0',如果您不需要,也不需要 返回一个字符串。)只需将指针初始化为buffer + sizeof(buffer),并在每次插入数字时预先递减。至 构造你返回的字符串: std::string( pointer, buffer + sizeof(buffer) )应该做到这一点。

至于循环,结束条件可能只是value == 0。 (每次你都会将value除以base,所以你就是这样 保证达到这个条件。)如果你使用do ... while, 而不只是while,你也保证至少有一位数 输出。

(我发布代码要容易得多,但是从那以后 这显然是家庭作业,我认为最好只是给出指示 关于需要做什么。)

编辑:我已添加了我的实施,并对您的新内容发表了一些评论 代码:

首先是评论:有一个非常误导的提示:“输入一个 二进制数“听起来像用户应输入二进制;如果你是 读入int,输入的值应为十进制。还有 我仍然是% 1000/ 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更复杂,因为它必须处理所有种类 可能的错误条件。它仍然可能比你简单 需要;你可能也想修剪空白等(甚至忽略 他们:输入010000000100 0000更容易出错。

(另外,由于尾随,find的结束迭代器有一个- 1 '\0'编译器插入digits。)

答案 2 :(得分:0)

实际上我不明白为什么你需要这么复杂的代码来完成你需要的东西。

首先,没有从二进制转换为八进制这样的事情(转换为/从十进制转换等同样如此)。机器总是以二进制方式工作,没有什么可以(或应该)做的。

这实际上是格式化的问题。也就是说,你如何打印一个数字作为八进制,你如何解析八进制数的文本表示。

修改

您可以使用以下代码在任何基地打印一个数字:

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);

答案 3 :(得分:0)

当你想要一个不同基数的数字时,OP要求生成的代码是你的科学计算器会做的。

我认为你的算法错了。只是看着它,我看到一个平方的功能。为什么?有一种简单的数学方法可以做你正在谈论的事情。获得数学部分后,就可以将其转换为代码。

如果你有铅笔和纸,没有计算器(类似于不使用预制功能),方法是取你所在的基础,将其改为基础10,然后改为你需要的基础。在你的情况下,基数为8,基数为10,基数为2.

这应该让你开始。你真正需要的是带有模数的if / else语句来获得余数。 http://www.purplemath.com/modules/numbbase3.htm

然后你必须弄清楚如何获得你想要的输出。也许将余数存储在数组中或输出到txt文件。

(对于像这样的问题,我想用应用数学加倍专业的原因)

由于你想要从十进制0-256转换,所以最简单的做函数,比如称它们为int binary(),char hex()和int octal()。首先执行二进制和八进制,因为它们只能由整数表示,因为它是最简单的。

答案 4 :(得分: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 ;
}