十进制到二进制,没有数组和二进制运算符(如"&")

Decimal to binary without arrays and binary-operators (like "&")

本文关键字:二进制 运算符 数组 十进制      更新时间:2024-05-24

我必须为大学做一项任务,编写一个将十进制数转换为二进制数的程序。由于我只是计算机科学的初级课程,所以还没有引入数组或逐位运算符(如"&"(。该程序需要仅使用基本运算符(+、-、*、%(和(如果为else,则为(编写。我的方法如下,但我总是得到相反的值。所以不是11000011。

#include <iostream>
int main()
{
int n,a;
std::cin >> n;

for (int i=n; n>0; --i) {

a = n%2;
std::cout << a;
n = n/2;

}
return 0;
}

有办法解决这个问题吗?

当前代码检查从LSB到MSB的二进制值是否存在,并按该顺序打印。解决这个问题的一种方法是从MSB到LSB进行检查。

#include <iostream>
int main(){
int n, a=1;
std::cin >> n;
while(2*a <= n)
a *= 2;                                                                                                               
while(a > 0){
if (n >= a){
std::cout << 1;
n -= a;
} else {
std::cout << 0;
}
a /= 2;
}
std::cout << std::endl;
return 0;
}

这不是一个很好的方法,我建议改进它或寻找替代品作为练习。

如果你知道你只能向后得到正确的输出,那么想想你能做些什么来解决这个问题。只需反转位即可。这里有一种只使用基本功能的方法。

#include <iostream>
int main()
{
int n,a;
int bitCount = 0;
std::string reversedBits;
std::cin >> n;

for (int i=n; n>0; --i) {
a = n % 2;
reversedBits += a + '0';
++bitCount;
n = n / 2;
}
for (int i = bitCount - 1; i >= 0; --i) {
std::cout << reversedBits[i];
}
return 0;
}

这并不是说这是最好的方法。找出几个解决这个问题的方法对你来说是一个很好的练习。

我将提出一个非常简单的解决方案,它本质上是纯算术的,不涉及任何可以用来解决这个问题的位级破解,也不涉及类中未涉及的数组。正如你所观察到的,你的方法会反过来给你一个二进制数。不要直接打印得到的数字,而是使用整数将计算的数字放在正确的位置,以正确的顺序保存计算的数字。

考虑一下这个片段:

#include <iostream>
int main()
{
int n,a;
int result = 0;
int position = 1;
std::cin >> n;

for (int i=n; n>0; --i) {
a = n%2;
n = n/2;

result += position * a;
position *= 10;
}

std::cout << result << std::endl;    
return 0;
}

追踪输入12的示例:

  1. 第一次迭代:a为零,因此Result=0,位置从1更新为10
  2. 第二次迭代:a再次为零,因此Result=0,位置从10更新为100
  3. 第三次迭代:a不是零,所以Result现在是100(位置*1(,位置从100更新为1000
  4. 第四次迭代:a为非零,结果变为100+1000=1100,位置从1000更新为10000

这里我提供了一个递归解决方案。

我还使用argv允许在命令行上进行多个输入,每个输入可以是十进制文本或十六进制文本。

我用的是字符串,而不是cin。请注意,它们都继承了相同的流输入操作。

#include <iostream>
using std::cout, std::cerr, std::endl, std::hex, std::dec;
#include <string>
using std::string;
#include <sstream>
using std::stringstream, std::istringstream;
#include <cstdint>

//  typical output    vvvvv      v   v   v   v   v
//  n:   7340032   0x700000   11100000000000000000000
//  commands -- both the same input value
//  ./dumy899d 7340032
//  ./dumy899d 0x700000
//
//  which can be mixed in the same argv list:
//  ./dumy899d  7340032  0x700000

// recursion max depth: bit width of n (32 on my system)
void to_binary_R (string& retVal, int n)
{
if (0 == n)  return;        // recursion termination clause
to_binary_R (retVal, n/2);  // (n / 2) shifts all bits of n to right 
// n is on the stack and will be unchanged when the PC returns,
// thus, during 'decurse':
int a = (n % 2)   +  '0';  // do computation, a is 0x30 or 0x31
//  int (0 or 1)    0x30 -- char is auto promoted to int
retVal += static_cast<char>(a);  // append-to-retVal
//        no-code-cast: 30, 31 become chars '0', '1' with cast
}
// i sometimes prefer to return a string 
//    (this can enable reducing cout-pollution)
string to_binary(int n) 
{
string s; s.reserve(64); // declare & reserve space
to_binary_R(s, n);       // fill
return s;
}    
// forward declartions
// returns true when user input has '0x' 
bool hexUI(const string& s);
void usage(); 

int main(int argc, char* argv[])
{
if (argc < 2) { usage(); return -1; }
for (int indx = 1; indx < argc; ++indx)
{
char* arg = argv[indx];  // instead of std::cin >> n;
stringstream ss(arg);
int nOrig = 0;
if (hexUI(arg)) { ss >> hex >> nOrig; } 
else            { ss >> dec >> nOrig; } 
if (!ss.good() && !ss.eof()) // when not good state that is not
{                            // caused by eof()
// notify user:
cerr << "nn ERR: ss is not good() (and not eof) "
<< "Maybe a hex parameter prefix is missing '0x'?n" 
<< endl;
return -2;
}
cout << "n  n:   " << dec << nOrig
<< "   0x"     << hex << nOrig
<< "   "       << to_binary(nOrig)
<< endl;
} // for (int indx = 1; indx < argc; ++indx)
return 0;
} // int main()

// returns true when user input specifies hex with '0x' prefix
bool hexUI(const string& s) { return (s.find("0x") != string::npos); }
void usage()
{
cerr << "n  err:  expecting 1 or more command line arguments, each argument is "
<< "n        either decimal-text or hex-text (marked with '0x' prefix) "
<< "n        values are displayed in decimal, binary, and hex"
<< endl;
cout << "n  The following info might be different on your system:"
<< "n  My development system: Linux 20.04, using g++ v9.3.0";
cout << "n             sizeof(int) : "
<< sizeof(int) << " bytes    "         // 4  bytes
<< (sizeof(int) * 8) << " bits";       // 32 bits
cout << "n        sizeof(long int) : "
<< sizeof(long int) << " bytes    "    // 8 bytes
<< (sizeof(long int) * 8) << " bits";  // 64 bits
// consider specifying the size, such as
cout << "n         sizeof(int64_t) : "
<< sizeof(int64_t) << " bytes    "     // 8 bytes
<< (sizeof(int64_t) * 8) << " bits"    // 64 bits
<< endl;
}

有办法解决这个问题吗?

我想到了另一个学徒,有三个步骤。

string toHex_ToBin(int n, bool slz)
{
// STEP 1: create hex encoding using stringstream and hex
stringstream ss;
ss << hex << n;
string s = ss.str();
// STEP 2: use these hex chars to append corresponding binary codes
//         to empty return string
string m_s; 
for (uint i = 0; i < s.size(); ++i)
{
switch (toupper(s[i]))
{
case '0': { m_s += "0000"; break; }
case '1': { m_s += "0001"; break; }
case '2': { m_s += "0010"; break; }
case '3': { m_s += "0011"; break; }
case '4': { m_s += "0100"; break; }
case '5': { m_s += "0101"; break; }
case '6': { m_s += "0110"; break; }
case '7': { m_s += "0111"; break; }
case '8': { m_s += "1000"; break; }
case '9': { m_s += "1001"; break; }
case 'A': { m_s += "1010"; break; }
case 'B': { m_s += "1011"; break; }
case 'C': { m_s += "1100"; break; }
case 'D': { m_s += "1101"; break; }
case 'E': { m_s += "1110"; break; }
case 'F': { m_s += "1111"; break; }
// default: assert(0); break; 
}  
// I leave this question to the reader, "would a 
// vector<string> hex2bin = {"0000", "0001", .. "1111"};
// simplify this effort? "
} // for loop
// STEP 3 - if requested by user (via bool slz)
if(slz) // suppress leading zero's
{
size_t pos = m_s.find('1'); // find left most one
if (pos != std::string::npos)
m_s.erase(0, pos);
}
return m_s;
}