好多年没更新了,工作后的第一个更新。

言归正传,前几天碰上一个小问题,简单地说就是将核对给机械臂的发的运动指令是否正确,但指令码是16进制补码,看得云里雾里,用自带的计算器发现,并没有将负数的补码转成10进制的指令,因此,就写了一个简单的转换程序,代码如下:

// 计算一个16进制补码表示的整数对应的十进制数
#include <tchar.h>  
#include <cmath>
#include <iostream>

#define MAXCHAR  9
#define MAXDIGIT 8

using namespace std;

int HexChar2Digit(char NumInComplement[], int NumDigit[], int charsize);

// 主函数
int _tmain(int argc, _TCHAR* argv[])
{
	int bitnum = 0, charsize = 16;
	int isNegNum = 0;
	int i, numbase;
	long long resultInDec = 0;
	char NumInComplement[MAXCHAR];
	int NumDigit[MAXDIGIT];

	cout << "输入计算的位数(8位,16位,32位):" << endl;
	cin >> bitnum;

	charsize = bitnum / 4;

	// 清空缓存区
	cin.clear();
	cin.ignore(numeric_limits<std::streamsize>::max(), '\n');

	cout << "输入16进制表示的补码(输入 'q', 退出):" << endl;
	cin.getline(NumInComplement, MAXCHAR);

	while (NumInComplement[0] != 'q') {
		// 判断是否为负数
		isNegNum = ((NumInComplement[0] - '0' >= 8) && (NumInComplement[0] - '0' <= 9))||
				   ((NumInComplement[0] - 'a' >= 0) && (NumInComplement[0] - 'a' <= 5))||
				   ((NumInComplement[0] - 'A' >= 0) && (NumInComplement[0] - 'A' <= 5));

		// 将补码字符串转换为十进制数
		HexChar2Digit(NumInComplement, NumDigit, charsize);

		resultInDec = 0;
		for (i = 0; i < charsize; i++) {
			resultInDec += NumDigit[charsize-1-i] * pow(16, i);
		}

		// 如果为负数,补码求补得到十进制数真值
		if (isNegNum) {
			resultInDec = resultInDec - pow(2, bitnum);
		}
		cout << "补码0x" << NumInComplement << "对应的十进制数:" << resultInDec << endl;

		cout << "输入16进制表示的补码(输入 'q', 退出):" << endl;
		cin.getline(NumInComplement, MAXCHAR);
	}


	return 0;
}

/* 函数名称:HexChar2Digit
*  函数功能:将字符表示的16进制码转换成对应的16进制基数(0,1,2,...,15)
*  函数输入:
*  NumInComplement:16进制码对应的字符串
*  charsize:        16进制码的长度
* 
*  函数输出:
*  NumDigit:        对应的16进制基数
*  
*  函数返回值:
*  1-转换正确,0-转换错误,字符串中有非法字符
*/
int HexChar2Digit(char NumInComplement[], int NumDigit[], int charsize)
{
	int i;

	for (i = 0; i < charsize; i++) {
		switch (NumInComplement[i])
		{
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			NumDigit[i] = NumInComplement[i] - '0';
			break;
		case 'a':
		case 'A':
			NumDigit[i] = 10;
			break;
		case 'b':
		case 'B':
			NumDigit[i] = 11;
			break;
		case 'c':
		case 'C':
			NumDigit[i] = 12;
			break;
		case 'd':
		case 'D':
			NumDigit[i] = 13;
			break;
		case 'e':
		case 'E':
			NumDigit[i] = 14;
			break;
		case 'f':
		case 'F':
			NumDigit[i] = 15;
			break;
		default:
			// 出现非法字符,失败返回
			return 0;
		}
	}

	// 转换成功
	return 1;
}

这里简单解释一下补码的概念,计算机中整数均采用补码的方式存储,补码相比于原码和反码,其0的表示方式是唯一的。

(1)对于正整数:其补码与原码相等,直接采用除基数取余方式可以直接得到,将正整数补码还原成十进制正整数直接按权相加即可;

(2)对于负整数:其处理比较麻烦,书上教材也给出了相应的转换公式,但实际上可以直接从字面上理解,比如,16位补码表示的-1为0xFFFF,其0xFFFF与其对应的相反数1,相加刚好为2的16次方,而2的16次方刚好是10000000000000000(1是溢出位,其实得到的是16个0),这就是“补”的直接含义:负数的补码+其相反数的补码=0(2的n次方)。

因此,负数补码对应的十进制数=按权展开的后的十进制数-(2的n次方)

测试结果如下:

以十进制-30431为例,采用自带的计算器校核,结果正确。

 

 

更多推荐

C++将16进制补码转换为十进制数