简体   繁体   English

优化转换算法

[英]Optimizing conversion algorithm

I have recently been working on a exercise in a book I have been reading.我最近一直在做我一直在读的一本书的练习。 The task was to create a program that prints all the numbers between 1-256 in their binary, octal and hexadecimal equivalents.任务是创建一个程序,以二进制、八进制和十六进制等价形式打印 1-256 之间的所有数字。 We were only supposed to use methods we had learned so far in the book, which meant only using for, while and do..while loops, if and else if statements, converting integers to ASCII equivalents and some more basic stuff (eg cmath and iomanip).我们只应该使用到目前为止在本书中学到的方法,这意味着只使用 for、while 和 do..while 循环、if 和 else if 语句、将整数转换为 ASCII 等价物和一些更基本的东西(例如 cmath 和伊曼尼普)。

So after some work, here is my result.所以经过一些工作,这是我的结果。 However, it is messy and un-elegant and obfuscated.然而,它是凌乱的、不优雅的和模糊的。 Does anyone have any suggestions to increase code efficiency (or elegance... :P) and performance?有没有人有任何建议来提高代码效率(或优雅......: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;
}

Any recommendations for improvement will be appreciated.任何改进建议将不胜感激。

You have already covered 'iomanip', which infers you've already covered 'iostream'.您已经涵盖了“iomanip”,这表明您已经涵盖了“iostream”。

If that's the case, have a look at the following:如果是这种情况,请查看以下内容:

#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

Break out the functions for each output type, then loop through the integer list and output each in turn by calling the function for each different format. Break out the functions for each output type, then loop through the integer list and output each in turn by calling the function for each different format.

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

Fundamental problem is that a function this long needs refactoring to be more modular.根本问题是这么长的 function 需要重构以更加模块化。 Imagine you are writing the code for someone else to use.想象一下,您正在编写代码供其他人使用。 How can they call your main ?他们怎么称呼你的main How do they understand what each section of code is doing?他们如何理解每一段代码在做什么? They can't.他们不能。 If you make each section of code that has a particular job to do callable as a function then it's easier to understand its intent, and to reuse later.如果您将具有特定工作的代码的每个部分都作为 function 进行调用,那么更容易理解其意图,并在以后重用。

Have you considered writing a general function that works with any base?您是否考虑过编写适用于任何基础的通用 function?

Converting a non-negative number to a generic base is simple... you just need to compute number % base and you get the least significant digit, then divide number by base and repeat to get other digits...将非负数转换为通用基数很简单...您只需要计算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);

Once you have a generic conversion function then solving your problem is easy... just call it with base=2, 8 and 16 to get the results you need as strings.一旦你有一个通用的转换 function 然后解决你的问题很容易......只需使用 base=2、8 和 16 调用它以获得你需要的字符串结果。

My answer may be a bit tongue in cheek, but我的回答可能有点讽刺,但是

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

will do the trick for the octal and hexadecimal versions;)将为八进制和十六进制版本解决问题;)

For the binary version, i'd use a flag initialized to 256, and compare it to your number with the AND operator.对于二进制版本,我会使用初始化为 256 的标志,并使用 AND 运算符将其与您的数字进行比较。 If true, print a 1, if not, print a 0. Then divide the flag by two.如果为真,则打印 1,如果不是,则打印 0。然后将标志除以 2。 Repeat until the flag is 1.重复直到标志为 1。

Pseudocode for the conversion from integer to binary从 integer 转换为二进制的伪代码

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

For the octal and hex values, i'm a bit rusty but looking around should guide you to samples you may adapt对于八进制和十六进制值,我有点生疏,但环顾四周应该会引导您找到您可能会适应的样本

Why make it any harder than it really is.为什么让它变得比实际更难。

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

Try this尝试这个

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 << ""
  }
}

Maybe something like this?也许是这样的?

#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");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM