西工大网络空间安全学院计算机系统基础实验一(45678)

接着来看第4个函数,int replaceByte(int x, int n, int c),看题目给出的例子,replaceByte(0x12345678,1,0xab) = 0x1234ab78。我们可以多写几个例子,进而找出规律,比如:

replaceByte(0x12345678,2,0xab) = 0x12ab5678

replaceByte(0x12345678,3,0xab) = 0xab345678

replaceByte(0x12345678,0,0xab) = 0x123456ab

replaceByte(0x12345678,1,0x00) = 0x12340078

由此我们猜测,返回值可能是(c<<(n<<3))|(~(0xFF<<(n<<3))&x),为什么呢?我们拿题目给的例子为例来讲。replaceByte(0x12345678,1,0xab) = 0x1234ab78,结果可以看成由0x0000ab00与0x12340078相或得到,那么该怎么得到0x0000ab00与0x12340078呢?发现0xab<<8即可得到0xab00,而0xab<<8 == 0xab<<(1<<3),进而发现可以通过(c<<(n<<3))得到0x0000ab00,接着如何得到0x12340078呢?发现0x12340078可由0x12345678&0xFFFF00FF得到,而x即为0x12345678,那么该如何得到0xFFFF00FF呢?发现0xFFFF00FF==~0x0000FF00,而0x0000FF00==0xFF<<(1<<3),即0xFF<<(n<<3)。所以综上所述,我们得到了(c<<(n<<3))|(~(0xFF<<(n<<3))&x),下面我们使用Python进行检验,如(图1:第4个函数——用Python验证想法)所示。经过Python验证,我们的想法是正确的,接着我们重复第1、2、3个函数的流程,使用VS code修改bits.c文件,使用"./dlc bits.c"与"./dlc -e bits.c"命令确保第4个函数中使用的运算符等满足要求,使用"make clean", "make btest"函数编译生成新的btest可执行文件,使用"./btest -f replaceByte"命令保证函数能产生正确的结果。如(图2:第4个函数)所示,成功编写第4个函数。

另外,发现第4个函数还可以再次修改,使得使用到的运算符再少一个,如(图3:优化后的第4个函数)所示。

**************************************************************************************************************

(图1:第4个函数——用Python验证想法)

************************************************************************************************************** 

**************************************************************************************************************

(图2:第4个函数)

**************************************************************************************************************

**************************************************************************************************************

 

(图3:优化后的第4个函数)

**************************************************************************************************************

接着看第5个函数,int mult3div2(int x), 看题目给出的三个例子:mult3div2(11) = 16; mult3div2(-9) = -13; mult3div2(1073741824) = -536870912(overflow)。先看第一个例子,mult3div2(11) = 16,11的十六进制形式为0xB, (0xB<<1)+0xB可以得到0x21,接着0x21>>1得到0x1,十进制形式为16,正好是第一个例子的结果。虽然如此,我们依然可以留心到0x21右移一位时,最低位的1被移走了,但是歪打正着,正好满足了向0舍入的要求。所以我们猜测,返回的表达式是((x<<1)+x)>>1。第二个例子,mult3div2(-9) = -13,-9的16进制形式为0xFFFF FFF7,((0xFFFF FFF7)<<1)+(0xFFFF FFF7)可以得到0xFFFF FFE5,接着0xFFFF FFE5>>1得到0xFFFF FFF2,十进制形式为-14。但是期望中的结果是-13,而不是-14。这时我们发现,0xFFFF FFE5右移一位时,最低位的1被移走了,而且与向0舍入背道而驰。第三个例子,mult3div2(1073741824) = -536870912(overflow),1073741824的十六进制形式为0x4000 0000,(0x4000 0000<<1)+0x4000 0000可以得到0xC000 0000,0xC000 0000>>1得到0xE000 000,十进制形式即为-536,870,912,正好是答案的形式。

现在整理一下,只有当(x<<1)+x的最低位为1,并且x的最高位也为1时,返回的结果需要在((x<<1)+x)>>1的基础上,再多加1,否则不需要加1,直接返回((x<<1)+x)>>1即可。但是,真的是这样子嘛???作者私底下偷偷试过几次,发现还需要添加一条附加条件:(x<<1)+x的最高位也为1。那么如何用表达式表示出来“(x<<1)+x的最低位为1、最高位为1,并且x的最高位也为1”呢?((((x<<1)+x)<<31)&((x<<1)+x)&x)>>31。因为(x<<1)+x被反复使用,所以为了节省运算符,我们选择设置temp=(x<<1)+x,这样子即可写作:((temp<<31)&temp&x)>>31。只有当(x<<1)+x的最低位为1,最高位为1,并且x的最高位也为1时,((temp<<31)&temp&x)>>31的结果为0xFFFFFFFF,否则即为0。注意!!!在这里千万不要简单的将((x<<1)+x)>>1与((temp<<31)&temp&x)>>31相加!!!应该将((temp<<31)&temp&x)>>31取反后加1,即~(((temp<<31)&temp&x)>>31)+1,然后再与((x<<1)+x)>>1相加,才是正确的表达式子。作者就是因为这个错误,改了好一会。仿照着第1、2、3、4个函数的方法,我们来检验我们的函数对不对。如(图4:第5个函数)所示。

最后,至于为什么要添加那一条,作者并不清楚,等以后有时间慢慢研究吧。

**************************************************************************************************************

(图4:第5个函数)

**************************************************************************************************************

第6个函数,int multFiveEighths(int x) ,执行效果应该类似于C语言中的x*5/8,而且向0舍入。这道题比第5题的难度更大。但我们不妨采用类似的方法,先确定大概的轮廓((x<<2)+x)>>3,接着再去细调。而细调的方法是,不断比较对于不同的x,两个表达式((x<<2)+x)>>3与x*5/8的值是否会有不同,以及会有多大的不同。观察发现似乎对于0到2147483647的正整数来说,((x<<2)+x)>>3与x*5/8的值相同,对于-1到-2147483648的负数来说,除非该负数能够整除8,否则 x*5/8=(((x<<2)+x)>>3)+1。而如果x这个负数能够整除8,则x<<29为0x0,并且x>>31=0xFFFF FFFF,写在一起即为(x>>31)&!(x<<29)。所以最终返回的表达式是:(((x<<2)+x)>>3)+((x>>31)&!!(x<<29))(注意这里采用了两个取非符号!!!这个地方很容易错)。仿照第1、2、3、4、5个函数的方法,我们来检验第6个函数的正确性,如(图5:第6个函数)所示。

**************************************************************************************************************

(图5:第6个函数)

**************************************************************************************************************

第7个函数,int addOK(int x, int y),判断x+y是否会发生溢出。如果会发生溢出,那么返回0,如果不会发生溢出,则返回1。而两个int类型变量相加会造成溢出的情况是:当两个正数相加得到的结果为负数,或者两个负数相加得到的结果为正数时,就会发生溢出。用"int sum=x+y"来保存x+y的值。返回!((~((x>>31)^(y>>31)))&((x>>31)^(sum>>31)))。虽然最终通过了,如(图6:第7个函数)所示,但是其中的函数逻辑并没有理清楚,还需要进行一轮又一轮的迭代与优化。

**************************************************************************************************************

(图6:第7个函数)

**************************************************************************************************************

第8个函数,int bitCount(int x),返回int型变量x的十六进制表示形式中1的个数。比如当x=5时,5为0x0101,有2个1,当x=7时,7为0x0111,有3个1。这道题比较复杂,使用到了“汉明重量”的知识。作者结合Java中对于函数bitCount的实现方法,简单修改了下代码,使其满足对于运算符等的要求,之后按照前7个函数相同的方法,写完了第8个函数,如(图7:第8个函数)所示:

**************************************************************************************************************

(图7:第8个函数)

**************************************************************************************************************

最后,45678这8个函数的代码如(图8:5个函数的C语言源代码)所示:

**************************************************************************************************************

int replaceByte(int x, int n, int c) {int temp = n<<3; return (c<<temp)|(~(0xFF<<temp)&x);
}
int mult3div2(int x) {int temp=(x<<1)+x; return (temp>>1)+(~(((temp<<31)&temp&x)>>31)+1);
}
int multFiveEighths(int x) {return (((x<<2)+x)>>3)+((x>>31)&!!(x<<29));
}
int addOK(int x, int y) {int sum=x+y;return !((~((x>>31)^(y>>31)))&((x>>31)^(sum>>31)));
}
int bitCount(int x) {int temp1 = 0x55|(0x55<<8)|(0x55<<16)|(0x55<<24);int temp2 = 0x33|(0x33<<8)|(0x33<<16)|(0x33<<24);int temp3 = 0xf|(0xf<<8)|(0xf<<16)|(0xf<<24);int n = x + ~((x >> 1) & temp1) + 1;n = (n & temp2) + ((n >> 2) & temp2);n = (n + (n >> 4)) & temp3;n = n + (n >> 8);n = n + (n >> 16);return n & 0x3f;
}

(图8:5个函数的C语言源代码)

**************************************************************************************************************

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/230650.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

达梦数据库使用

达梦数据库使用 &#x1f4d1;前言 本文主要是【达梦数据库】——达梦数据库简单使用的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他…

PointerEvent实现拖动滑块效果(支持左右吸附)

效果展示&#xff1a; 参数说明&#xff1a; adsorbLen &#xff1a;为0则不吸附&#xff0c;不为0则为左右吸附的距离。也可以自己修改左右的吸附长度。 代码&#xff1a; <template><div class"slider-box" ref"sliderBoxRef"><div re…

洛谷100题DAY8

36.P1416 攻击火星 此题找出规律即可 #include<bits/stdc.h> using namespace std; int n; int main() {cin >> n;cout << max(0, n - 2);return 0; } 37.P1551 亲戚 并查集模板题目 两个人如果使亲戚就合并建立联系&#xff0c;最后进行查找即可 #incl…

【送书活动二期】Java和MySQL数据库中关于小数的保存问题

之前总结过一篇文章mysql数据库&#xff1a;decimal类型与decimal长度用法详解&#xff0c;主要是个人学习期间遇到的mysql中关于decimal字段的详解&#xff0c;最近在群里遇到一个小伙伴提出的问题&#xff0c;也有部分涉及&#xff0c;今天就再大致总结一下Java和MySQL数据库…

一个00后女生在csdn创作1095的创作纪念日

大家好&#xff0c;我是你们熟悉的微枫奶糖 肥晨&#xff0c;今天收到私信&#xff0c;突然发现&#xff0c;我来到CSDN已经1095天了。让我来分享一下吧~ 机缘 不知不觉来csdn已经1095天了&#xff0c;祝贺我在CSDN的创作纪念日&#xff01; 这是一个非常值得纪念的日子&…

PlantUML语法(全)及使用教程-类图

目录 1. 类图1.1、什么是类图1.2、元素声明1.3、类之间的关系1.4、关系上的标签1.5、在元素名称和关系标签中使用非字母1.6、添加方法 1. 类图 类图的设计语法与编程语言的传统语法相似。这种相似性为开发人员提供了一个熟悉的环境&#xff0c;从而使创建图表的过程更简单、更直…

编程实现bf算法

BF算法&#xff08;Brute Force算法&#xff09;是一种朴素的字符串匹配算法&#xff0c;其基本思想是在文本串中不断地比较模式串和文本串中的子串&#xff0c;直到找到匹配的位置或者搜索完整个文本串。 下面是用Python实现BF算法的代码&#xff1a; def bf_search(text, p…

【Openstack Train安装】十、Neutron安装

Neutron&#xff0c;是Openstack中的一大核心组件&#xff0c;设计目标是实现“网络即服务&#xff08;Networking as a Service&#xff09;”。为了达到这一目标&#xff0c;在设计上遵循了基于 SDN 实现网络虚拟化的原则&#xff0c;在实现上充分利用了 Linux 系统上的各种网…

【LeetCode】每日一题 2023_11_29 无限集中的最小数字(哈希/堆)

文章目录 刷题前唠嗑题目&#xff1a;无限集中的最小数字题目描述代码与解题思路偷看大佬题解 结语 刷题前唠嗑 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 今天的题目也比较的简单&#xff0c;因为数据量不大&#xff0c;所以什么做法都能过的去 题目&a…

Django快速搭建静态网页

Django的快速搭建 这个是例子 这个是一个目录 项目名称&#xff1a;项目似乎被命名为DJ0928&#xff0c;这是Django项目的根目录。 文件都是Django项目的核心配置文件。 settings.py 包含了项目的配置设置。urls.py 定义了项目的URL路由。wsgi.py 和 asgi.py 分别用于Web服务器…

Java实现通过经纬度求两个任意地点在球面上的距离

我们在实际开发中会获取对应的经纬度&#xff0c;可以使用ES大数据搜索引擎进行计算对应区域的数据&#xff0c;那我们在如何根据两个经纬度获取对应的球面距离&#xff0c;就是在地球上从一个地点到另一个地点的直线距离 工具类如下: public class GeoUtils {// 地球半径&am…

AI视频智能分析识别技术的发展与EasyCVR智慧安防视频监控方案

随着科技的不断进步&#xff0c;基于AI神经网络的视频智能分析技术已经成为了当今社会的一个重要组成部分。这项技术通过利用计算机视觉和深度学习等技术&#xff0c;实现对视频数据的智能分析和处理&#xff0c;从而为各个领域提供了广泛的应用。今天我们就来介绍下视频智能分…