华为2018春招笔试题目 字节流解析与长整数相乘

本文深入探讨了字节和位的基本概念,包括它们在计算机数据存储中的作用,以及如何进行位运算和进制转换。通过具体示例,如解析二进制字节流和长整数相乘,详细讲解了相关算法的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基础知识杂烩:

字节也叫Byte,是计算机数据的基本存储单位,

bit存储内容是0和1,bit是计算机中最小的储存单位

一个Byte是由8个bit组成,它是最小的可寻址单元 ,1个字节等于8位二进制。1B(Byte)=8b(bit)

八个bit可以存储基本的元素 2^8数  例如:abcd1234和各种符号

       在ASCII码中,一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间,一个字节是8位,一个汉字编码两个字节是十六位。英文标点占一个字节,中文标点占两个字节。一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制。最小值:0 最大值:255 。如一个ASCII码就是一个字节

二进制占一个bit
八进制占三个 bit
十六进制占四个bit
十进制一般按实际来算,7以下占3个,8,9占4个。

例如:{0x62, 0x80}是16进制,对应二进制为“0110  0010  1000   0000”

华为2018春招笔试题目二 字节流解析

      根据数值占用BIT数,按顺序从输入字节流中解析出对应数值,解析顺序按输入数组astElement索引升序; 
void Decode(unsigned int uiInputLen, unsigned char aInputByte[], unsigned int uiElementNum, ELEMENT_STRU astElement[]); 
unsigned int uiInputLen:字节数组(流)长度 
unsigned char aInputByte:字节数组(流) 
unsigned int uiElementNum:解析数值个数 
ELEMENT_STRU astElement[]:数值的结构数组指针,含义如下 
Struct 

unsigned int uiElementLength; //表示uiElementValue占用BIT数,范围1~32 
unsigned int uiElementValue; //从字节流中按顺序解析的数值,用于输出 
}ELEMENT_STRU;

输入描述: 
字节数组长度uiIutputLen为3; 
字节数组aInputByte[3]为{0x62, 0x80, 0x00},对应二进制为“0110 0010, 1000 0000, 0000 0000”; 
解析数值个数uiElementNum为2; 
数值[0]的值占4个bit,即astElement[0].uiElementLength = 4; 
数值[1]的值占5个bit,即astElement[1].uiElementLength = 5; 
输出描述: 
数值[0]的值为6,二进制为“0110”,即astElement[0].uiElementValue = 6; 
数值[1]的值为5,二进制为“0010 1”,即astElement[1].uiElementValue = 5;

示例1 
输入 

0x62 0x80 0x00 



输出 

5

思路

   我们输入的“0x62 0x80 0x00 ”是以二进制01的形式连续排列的,要求我们从二进制字节流取出指定数目的bit,然后转化为十进制输出。例如 0x62 0x80 实际上连在一起是 0110 0010 1000 0000,输入4,表示取4个bit得到0110,转化为十进制是6,接着输入5,表示接着取5个bit得到00101,转化为十进制是5。另外,这道题的难点主要在于进制准换以及相关的输入操作。
实例:

#include<iostream>
#include<string>
#include<vector>
using namespace std;

int main() {
	int len;                            //输入字节数组长度
	cin >> len;
	vector<long long> lens(len);
	for (int i = 0; i < len; ++i) {
		cin >> hex >> lens[i];         //字节数组中的元素,输入的是16进制数
	}

	int num; 
	cin >> num;                       //解析数值的个数ElementNum
	vector<int> nums(num);            //定义一个包含num个int元素的STL向量
	for (int i = 0; i < num; ++i) {
		cin >> dec >> nums[i];        //每个数值所占的bit数
	}

	vector<bool> bits;
	//len的值分别是98,128,0(0x62 0x80 0x00)
	for (int len : lens) {            //遍历lens中的值,for(元素类型t 元素变量x : 遍历对象obj)
		for (int i = 0x80; i; i >>= 1) {    //i是判断条件,为0时退出;i>>=1将i的二进制值右移1
			bits.push_back(len&i);          //使用1000 0000对0x62(0110 0010)做"与"运算,将"1""0"提取出来分别存入bits向量
		}
	}

	int start = 0;
	long long result = 0;
	for (int num : nums) {   //nums中存 4,5
		for (int i = 0; i<num; ++i) {
			result = 2 * result + bits[i + start];  //取出4个bit位,将其转换为十进制
		}
		cout << result << endl;

		result = 0;
		start += num;                     //设置第二次循环的起始bit位
	}
	system("pause");
	return 0;
}

for ( int num:nums ):   括号里即声明一个变量num遍历数组nums,把nums中的值按顺序赋给num。

题目三 长整数相乘

输入两个长整数,以空格隔开 ,输出相乘后的结果

示例1 
输入 
-12341234 
43214321 
输出 
-533318047612114

思路

主要考察大数运算,基本上做法都是转化成字符串,实现两个数的乘法(小学学过的那种),实现关键在于进位。此外,还要留意输入数字可能是负值,在字符串处理时要注意。

代码实现

#include <iostream>  
#include <string>
#include <vector>
using namespace std;


int multiply(const string strMultiplierA, const string strMultiplierB, string &strRst)
{
	//测试是否有乘数(字符串)为空  
	if (strMultiplierA.empty() || strMultiplierB.empty())
		return -1;

	string strA = strMultiplierA;
	string strB = strMultiplierB;
	int lenA = strA.length();
	int lenB = strB.length();
	int strRst_length = 0;
	int lenC = (lenA + 1)*(lenB + 1);
	// 创建了一个 int 类型lenC个元素,且值均为0的vecotr容器pC
	vector<int> pC(lenC, 0); //逆序存放的结果  
	vector<int> pA(lenA, 0); //逆序存放的乘数A
	vector<int> pB(lenB, 0); //逆序存放的乘数B

	//把乘数逆序放到数组pA中,若A是12345,则pA是54321  
	for (int index = 0; index != strA.size(); index++)
		pA[lenA - 1 - index] = strA[index] - '0';     //   减'0'会把字符串转化为数字整型

	for (int index = 0; index != strB.length(); index++)
		pB[lenB - 1 - index] = strB[index] - '0';

	//每个位循环相乘
	for (int iB = 0; iB < lenB; iB++) {
		for (int iA = 0; iA < lenA; iA++) { //pA的每个位循环与pB[iB]相乘
											//pC[iA+iB]利用iB起到移位的作用,如iB是十位数,则在乘法计算中要向后移动移位。  
			int temp = pC[iA + iB] + pA[iA] * pB[iB];
			pC[iA + iB] = temp % 10;//余数
			int carry = temp / 10; //进位  

			int x = iA + iB + 1;
			//lenC足够大;大数相加与数相乘同时计算,进位有可能是多位数  
			while (carry != 0) {
				//进位不等于0
				pC[x] = pC[x] + carry % 10;//若前面有进位,则提前把进位加到求和结果p[x]上  
				carry = carry / 10;
				x++;
			}
		}
	}

	//判断结果有几位 
	while (lenC--) {
		if (pC[lenC] != 0) {
			strRst_length = lenC + 1;
			break;
		}
	}
	char ch;
	for (int i = strRst_length - 1; i >= 0; i--)  //把结果放入字符串中 (注意倒序) 
	{
		ch = pC[i] + '0';                        //数字转字符
		strRst.push_back(ch);
	}
	if (strRst.empty())//如果结果为0,则输出字符串为“0”  
		strRst = "0";
	return 0;
}


int main() {
	string A;
	string B;
	cin >> A; cin >> B;
	int neg_count = 0;
	if (A[0] == '-') {
		A = A.substr(1, A.size() - 1);
		neg_count++;
	}
		
	if (B[0] == '-') {
		B = B.substr(1, B.size() - 1);
		neg_count++;
	}
			
	string C = "\0";//保存结果
	multiply(A, B, C);
	if(neg_count==1)
		cout << "-";
	cout << C << endl;

	system("pause");
	return 0;

}

from:https://blog.youkuaiyun.com/songbinxu/article/details/79647723

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值