0

我目前正在开发一个将二进制数转换为八进制数的基本程序。它的任务是打印一个包含 0-256 之间所有数字的表格,以及它们的二进制、八进制和十六进制等价物。该任务只要求我使用我自己的代码(即使用循环等而不是内置函数)。我制作的代码(目前非常混乱)如下(这只是一个片段):

        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;

}

4

5 回答 5

2

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

当然,显而易见的解决方案是使用预先存在的功能来做到这一点(喜欢{ char buf[32]; snprintf(buf, sizeof buf, "%o", binaryValue); }并完成,但如果你真的想“手动”做,你应该考虑使用位操作:

  • 用于binaryValue & 3屏蔽三个最低位。这些将是您的下一个八进制数字(三位是 0..7,这是一个八进制数字)。
  • 用于binaryValue >>= 3移动数字以使三个新位进入最低位置
  • 之后反转数字,或者(如果可能)从字符串缓冲区的末尾开始并向后发出数字
于 2011-07-07T08:27:44.140 回答
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在最后调用,然后返回它。char[]否则:只要你把它做得足够大,C 风格就可以很好地工作。(sizeof(unsigned) * CHAR_BITS + 2是绰绰有余的,即使是有符号的,即使'\0'在结尾有 a ,如果你返回一个字符串,你就不需要了。) 只需初始化指向 的指针buffer + sizeof(buffer),并在每次插入数字时预先递减。要构造您返回的字符串: std::string( pointer, buffer + sizeof(buffer) )应该可以解决问题。

至于循环,结束条件可以简单地是value == 0. (您每次都将除以valuebase因此可以保证达到此条件。)如果您使用 a do ... while,而不仅仅是 a while,则还可以保证输出中至少有一个数字。

(对我来说,只发布代码会容易得多,但由于这显然是家庭作业,我认为最好只是给出需要做什么的指示。)

编辑:我已经添加了我的实现,以及对你的新代码的一些评论:

首先是评论:有一个非常误导性的提示:“输入二进制数”听起来用户应该输入二进制;如果您正在阅读int,则输入的值应该是十进制的。还有我不明白的% 1000/ 1000% 10和。/ 10无论你在做什么,如果没有% 8and就不可能是正确的/ 8。试试看:"128"例如 input ,看看你得到了什么。

如果你想输入二进制,那么你真的必须输入一个字符串,然后自己解析它。

我的转换代码本身是:

//! \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

其实我不明白为什么你需要这么复杂的代码来完成你所需要的。

首先,不存在从二进制到八进制的转换(从十进制转换为/从十进制等转换也是如此)。机器总是以二进制工作,对此您无能为力(或不应该)。

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

编辑:

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

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 文件。

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

由于您想要从十进制 0-256 进行转换,因此最容易创建函数,例如调用它们 int binary()、char hex() 和 int octal()。首先做二进制和八进制,因为这将是最简单的,因为它们只能用整数表示。

于 2011-07-07T08:59:42.117 回答
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 回答