【问题标题】:Optimizing conversion algorithm优化转换算法
【发布时间】:2011-07-08 14:35:30
【问题描述】:

我最近一直在做我一直在阅读的书中的练习。任务是创建一个程序,以二进制、八进制和十六进制等价形式打印 1-256 之间的所有数字。我们只应该使用到目前为止在本书中学到的方法,这意味着只使用 for、while 和 do..while 循环、if 和 else if 语句、将整数转换为 ASCII 等价物和一些更基本的东西(例如 cmath 和伊曼尼普)。

所以经过一些工作,这是我的结果。然而,它是凌乱的、不优雅的和模糊的。有没有人对提高代码效率(或优雅...:P)和性能有任何建议?

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

int main()
{
int decimalValue, binaryValue, octalValue, hexadecimalValue, numberOfDigits;
cout << "Decimal\t\tBinary\t\tOctal\t\tHexadecimal\n\n";
for (int i = 1; i <= 256; i++)
{
    binaryValue = 0;
    octalValue = 0;
    hexadecimalValue = 0;
    if (i != 0) 
    {
    int x, j, e, c, r = i, tempBinary, powOfTwo, tempOctal, tempDecimal;
    for (j = 0; j <=8; j++) //Starts to convert to binary equivalent
    {
        x = pow(2.0, j);
        if (x == i)
        {
              powOfTwo = 1;
              binaryValue = pow(10.0, j);
              break;
        }
        else if (x > i)
        {
              powOfTwo = 0;
              x /= 2;
              break;
        }
    }
    if (powOfTwo == 0)
    {
    for (int k = j-1; k >= 0; k--)
    {
        if ((r-x)>=0)
        {
           r -= x;
           tempBinary = pow(10.0, k);
           x /= 2;
        }
        else if ((r-x)<0)
        {
           tempBinary = 0;
           x /= 2;
        }
        binaryValue += tempBinary;
    }
    } //Finished converting
    int counter = ceil(log10(binaryValue+1)); //Starts on octal equivalent
    int iter;
    if (counter%3 == 0)
    {
       iter = counter/3;
    }
    else if (counter%3 != 0)
    {
       iter = (counter/3)+1; 
    }
    c = binaryValue;
    for (int h = 0; h < iter; h++)
    {
        tempOctal = c%1000;
        int count = ceil(log10(tempOctal+1));
        tempDecimal = 0;
        for (int counterr = 0; counterr < count; counterr++)
        {
            if (tempOctal%10 != 0)
            {
                 e = pow(2.0, counterr);
                 tempDecimal += e;
            }
            tempOctal /= 10;
        }
        octalValue += (tempDecimal * pow(10.0, h));
        c /= 1000;
    }//Finished Octal conversion
    cout << i << "\t\t" << binaryValue << setw(21-counter) << octalValue << "\t\t";
    int c1, tempHex, tempDecimal1, e1, powOf;
    char letter;
    if (counter%4 == 0)//Hexadecimal equivalent
    {
       iter = counter/4;
    }
    else if (counter%4 != 0)
    {
       iter = (counter/4)+1;
    }
    c1 = binaryValue;
    for (int h = 0, g = iter-1; h < iter; h++, g--)
    {
        powOf = g*4;
        if (h == 0)
        {
              tempHex = c1 / pow(10.0, powOf);
        }
        else if (h > 0)
        {
             tempHex = c1 / pow(10.0, powOf);
             tempHex %= 10000;
        }
        int count = ceil(log10(tempHex+1));
        tempDecimal1 = 0;
        for (int counterr = 0; counterr < count; counterr++)
        {
            if (tempHex%10 != 0)
            {
                 e1 = pow(2.0, counterr);
                 tempDecimal1 += e1;
            }
            tempHex /= 10;
        }
        if (tempDecimal1 <= 9)
        {
        cout << tempDecimal1;
        }
        else if (tempDecimal1 > 9)
        {
        cout << char(tempDecimal1+55); //ASCII's numerical value for A is 65. Since 10-15 are supposed to be letters you just add 55
        }
    }
    cout << endl;
    }
}
system("pause");
return 0;
}

我们将不胜感激任何改进建议。

【问题讨论】:

  • 我假设你不能使用 printf?
  • @fvu 在这种特殊情况下,变量 j 用于除特定 for 循环之外的其他地方,因此在 for 标头之外进行声明。

标签: c++ algorithm optimization


【解决方案1】:

您已经涵盖了“iomanip”,这意味着您已经涵盖了“iostream”。

如果是这样,请查看以下内容:

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

int x = 250;
cout << dec << x << " " 
     << oct << x << " "
     << hex << x << "\n"
     << x << "\n";       // This will still be in HEX

【讨论】:

  • 我的 C++ 肯定生锈了,我忘记了 cout 及其各种格式化选项
  • 请注意,操纵器通常具有 PE​​RSISTENT 效果(setw 是一种特殊情况)。因此,在循环中重复执行时,上述内容可能不会像您认为的那样。 ;-) 当然,在您修复了示例之后,其他人可能会觉得这条评论有点奇怪,所以,如果读者觉得这很奇怪,那么代码可能已经修复了。干杯,
  • 这将是最简单的方法。但是,该任务要求我们不要使用内置函数,并使用我们自己的算法在 1-256 之间转换每个值。还是谢谢!
  • @samy 更新了答案以说明潜在问题。
【解决方案2】:

分解出每种输出类型的函数,然后循环遍历整数列表并通过调用每种不同格式的函数依次输出。

for (int i = 1; i <= 256; ++i)
{
  printBin(i);
  printHex(i);
  printOct(i);
}

根本问题是这么长的函数需要重构以更加模块化。想象一下,您正在编写代码供其他人使用。他们怎么会打电话给你的main?他们如何理解每一段代码在做什么?他们不能。如果您将具有特定工作的每一段代码都作为函数调用,那么就更容易理解其意图并在以后重用。

【讨论】:

  • 至少了解 Emile 的人是在寻求代码建议,而不是简单的“使用内置函数”。
  • +1-1=0:建议模块化,但是这个 C++,而不是 Java:完全没有理由使用静态方法创建一个类会成为更好的解决方案。 .
  • @6502 - 你说得对,这更像是一个 C# 或 Java 习语 - 谢谢
【解决方案3】:

您是否考虑过编写一个适用于任何基础的通用函数?

将非负数转换为通用基数很简单...您只需计算number % base 并得到最低有效位,然后将number 除以base 并重复以获得其他数字。 ..

std::string converted_number;
do {
    int digit = number % base;
    converted_number = digits[digit] + converted_number;
    number = number / base;
} while (number != 0);

一旦你有了一个通用的转换函数,那么解决你的问题就很容易了......只需使用 base=2、8 和 16 调用它,以获得你需要的字符串结果。

【讨论】:

    【解决方案4】:

    我的回答可能有点诙谐,但是

     printf ("%u %o %x \n", value, value, value);
    

    会为八进制和十六进制版本解决问题;)

    对于二进制版本,我会使用初始化为 256 的标志,并使用 AND 运算符将其与您的数字进行比较。如果为真,则打印 1,如果不是,则打印 0。然后将标志除以 2。重复直到标志为 1。

    整数到二进制转换的伪代码

    int flag = 256
    do 
    {
    if (flag && value)
    print "1"
    else
    print "0"
    flag = flag >> 1 // aka divide by two, if my memory serves well
    } while flag > 1
    

    对于八进制和十六进制值,我有点生疏,但环顾四周应该会引导您找到可以适应的样本

    【讨论】:

      【解决方案5】:

      为什么要让它变得比实际更难。

      for (int i = 1; i <= 256; ++i)
      {
          std::cout << std::dec << i << "\t" << std::oct << i << "\t" << std::hex << i << std::endl;
      }
      

      【讨论】:

      • 正如我之前对 Chad 所说:任务不是使用内置函数,而是创建和设计自己的算法,将 1-256 之间的所有数字转换为二进制、八进制和十六进制。另一方面,如果不是这样,我肯定会使用你的方法! :D
      【解决方案6】:

      试试这个

      using namespace std;
      
      template <typename T>
      inline void ShiftMask(T& mask) {
          mask = (mask >> 1) & ~mask;
      }
      
      template < typename T >
      std::ostream& bin(T& value, std::ostream &o)
      {
          T mask = 1 << (sizeof(T) * 8 - 1);
      
          while (!(value & mask) && (mask != 0)) ShiftMask(mask);
      
          while (mask) {
              o << (value & mask ? '1' : '0');
              ShiftMask(mask);
          }
      
          return o;
      }
      
      int main(void) {
        for (int i=0; i<256;i++) {
          bin(a, std::cout);
          cout << " " << oct << i;
          cout << " " << dec << i;
          cout << " " << hex << i;
          cout << ""
        }
      }
      

      【讨论】:

        【解决方案7】:

        也许是这样的?

        #include "stdio.h"
        int main(){
            char Chars[16]= {48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70};
            for(int n = 1;n != 256; n++)
            {
                {//decimal
                    printf("%i\t", n); 
                }
                {//Hexadecimal
                    char L, R;
                    R = (n & 0x0F) >> 0;
                    L = (n & 0xF0) >> 4;
                    printf("%c%c\t", Chars[L], Chars[R]);
                }
                {//Octal
                    char L, M, R;
                    R = (n & 0x07) >> 0;
                    M = (n & 0x38) >> 3;
                    L = (n & 0xC0) >> 6;
                    printf("%c%c%c\t", Chars[L], Chars[M], Chars[R]);
                }
                {//Binary
                    char B0, B1, B2, B3, B4, B5, B6, B7;
                    B0 = (n & 0x01) >> 0;
                    B1 = (n & 0x02) >> 1;
                    B2 = (n & 0x04) >> 2;
                    B3 = (n & 0x08) >> 3;
                    B4 = (n & 0x10) >> 4;
                    B5 = (n & 0x20) >> 5;
                    B6 = (n & 0x40) >> 6;
                    B7 = (n & 0x80) >> 7;
                    printf("%c%c%c%c%c%c%c%c\n", Chars[B0], Chars[B1], Chars[B2], Chars[B3], Chars[B4], Chars[B5], Chars[B6], Chars[B7]);
                }
                printf("256\t100\t400\t100000000\n");
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2016-07-30
          • 2023-02-03
          • 2021-01-01
          • 1970-01-01
          • 2015-10-27
          • 2013-12-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多