西工大计算机学院计算机系统基础实验一(函数编写15~17)

还是那句话,稳住心态,稳住心态,稳住心态。心里别慌,心里别慌,心里别慌。

第15题,howManyBits,返回用二进制补码形式表示x所需的最小二进制位数。比如howManyBits(12) = 5,12可以被表示为0 1100B,最高位的0为符号位,这样子一共需要5个二进制位来表示x;再比如howManyBits(298) = 10,298可以被表示为01 0010 1010B,最高位的0为符号位,这样子一共需要10个二进制位来表示x;接着比如howManyBits(-5) = 4,-5可以被表示为0xFFFF FFFB,从左到右删除掉连续的1,但最后仍还剩下一个1,即得到了1011B,最高位的1为符号位,这样子一共需要4个二进制位来表示x(1011B各位取反加一可以得到0101B也就是5);接着howManyBits(0)  = 1,0可以被表示为0B,符号位为0,一共需要1个二进制位;howManyBits(-1) = 1,-1可以被表示为1B,符号位为1,一共需要1个二进制位;在这里0被当作正的0而不是负的0,就好像int型的0是0x0而不是0x8000 0000一样。最后一个例子howManyBits(0x80000000) = 32,0x8000 0000,从左到右删除掉连续的1,但最后仍还剩下一个1,结果还是0x8000 0000,最高位为符号位,这样子一共需要32个二进制位来表示x。那么我们该怎么写出这个函数呢?

为了便于思考,我们首先先分两类讨论。第一类,当x为正数时,我们可以简单的将x*2,也就是将x左移一位,然后统计x<<1中有几位,比如x=5=101B,x<<1=1010B,这时x<<1中有4位,所以用二进制补码表示x需要4位,而事实也正好是这样;第二类,当x为负数时,就不能简单的统计x<<1中的位数了,比如-5=0xFFFF FFFB,(-5)<<1之后的结果还是0xFFFF FFF6,统计其中的位数,发现还是32位,所以不能简单的统计x<<1中的位数。那么我们该如何去掉从左到右删除掉连续的1,只留下一个1呢?发现可以通过异或的方法,x^(x<<1),这样子就去掉了连续的1,只留下一个1啦!而对于正数来说,x^(x<<1)中的比特位数与x<<1一样。所以综上所述,无论x是正数还是负数,都可以只统计x^(x<<1)中的比特位数。在这里引入变量"int temp=x^(x<<1)"。

接着如何高效的统计temp中的比特位数呐?有这么一种思路,先看能不能用16位表示x,如果16位不够,那么记录下来16位不够,然后让temp=temp>>16,接着看8位够不够表示此时的temp,也就是8位够不够表示x^(x<<1)的高8位,如果能够的话,怀疑8位多了,所以记录下来8位足够,然后temp还是等于temp,接着看4位够不够表示此时的temp... ...下面结合例子来讲讲吧: 

假设有一个变量x,其十六进制表示形式为0x0177 7FFF,那么temp为0x0399 8001。先看0x0399 8001可以被用16位非补码表示嘛?(因为temp=x^(x<<1)已经考虑了符号位的问题,所以这里问题只需要简简单单的考虑即可)发现不够,所以记录下来先需要16位,这样子低位的16位已经被记录下来了,把高16位拿到低16位看低16位的情况,也就是看0x0000 0399。0x0000 0399能被8位表示嘛?发现不够,所以记录下来还需要8位,这样子第16到第23位已经被记录下来了,再把8位拿到低位,即得到了0x0000 0003。0x0000 0003能被4位表示嘛?发现绰绰有余,所以记录下来不需要4位,然后不把4位拿到低位,还是0x0000 0003,它能被2位表示嘛?发现刚刚好,但是仍然记录下来不需要2位,然后不把2位拿到低位,还是0x0000 0003,他能被1位表示嘛?发现不够,所以记录下来需要1位。这时还少计算了1位,所以还要加1。

现在结合案例,我们思考该如何编写代码呢?首先如何判断能不能被16、8、4、2、1位表示呢?右移16、8、4、2、1位之后两次逻辑取非即可。那么如何记录下来需要16、8、4、2、1位呢?右移16、8、4、2、1位之后两次逻辑取非的结果,再左移4、3、2、1、0位即可。那么如何判断是否需要把temp的高位移到低位呢?让temp右移“右移16、8、4、2、1位之后两次逻辑取非的结果”即可。如果不能被16、8、4、2、1位表示,那么“右移16、8、4、2、1位之后两次逻辑取非的结果”就会是0;如果能被16、8、4、2、1位表示,那么“右移16、8、4、2、1位之后两次逻辑取非的结果”就会是1。同样也只有不能被16、8、4、2、1位表示的时候,才需要把temp的高位移到低位,此时“右移16、8、4、2、1位之后两次逻辑取非的结果”就会是1,让temp右移“右移16、8、4、2、1位之后两次逻辑取非的结果”,也正好实现了把temp的高位移到低位。代码如 图1:编写第15个函数howManyBits 所示。检查该函数的过程如 图2:检查第15个函数howManyBits 所示。

    int temp = x ^ (x << 1);int bit_16,bit_8,bit_4,bit_2,bit_1;bit_16 = !!(temp >> 16) << 4;temp = temp >> bit_16;bit_8 = !!(temp >> 8) << 3;temp = temp >> bit_8;bit_4 = !!(temp >> 4) << 2;temp = temp >> bit_4;bit_2 = !!(temp >> 2) << 1;temp = temp >> bit_2;bit_1 = !!(temp >> 1);return 1 + bit_1 + bit_2 + bit_4 + bit_8 + bit_16;

图1:编写第15个函数howManyBits) 

图2:检查第15个函数howManyBits

接着第16个函数,isNonZero,不使用逻辑非运算符!,检查x是否非0,比如isNonZero(3) = 1, isNonZero(0) = 0。怎么办呢?想一想发现,除了0之外,+1和-1位或的结果为0xFFFF FFFF,+2与-2位或的结果也是0xFFFF FFFF,+3与-3位或的结果也是0xFFFF FFFF... ...+2147483627与-2147483647位或的结果还是0xFFFF FFFF,甚至-2147483648与+2147483648(虽然不存在)位或的结果也还是0xFFFF FFFF,而+0与-0位或的结果却是0。利用这个性质,我们可以写出如 图3:编写第16个函数isNonZero 所示的代码。检查第16个函数的过程如 图4:检查第16个函数isNonZero 所示。

  int ret = ~x + 1;  ret = ret | x;       return (ret >> 31) & 1;

图3:编写第16个函数isNonZero

图4:检查第16个函数isNonZero

第17个函数,isPower2,判断x是不是2的1、2、3、4... ...次幂,如果是的话,返回1,否则返回0。我们该怎么做这道题呢? 注意没有负数是2的多少次幂。顺着这个思路,我们首先排除0和负数,排除0可以用!!x表示,排除负数可以用!(x>>31)表示。这时如何判断x是不是2的1、2、3、4... ...次幂呢?我们关注这些数的性质,0x0000 8000,0x0000 4000,我们发现其仅有除第一位以外的一位为1,其余位全部为0,这些数加上0xFFFF FFFF之后的结果,与这些本身位与的结果一定为0,而其它数加上0xFFFF FFFF之后再与本身位与的结果必不为0。所以我们可以利用这个性质,写出表达式!(x&(x+~0))。最终的代码如 图5:编写第17个函数isPower2 所示,检查过程如 图6:检查第17个函数isPower2 所示。

  int y = x+~0;return !(x&y)&!(x>>31)&!!x;

图5:编写第17个函数isPower2

图6:检查第17个函数isPower2) 

/* howManyBits - return the minimum number of bits required to represent x in*             two's complement*  Examples: howManyBits(12) = 5*            howManyBits(298) = 10*            howManyBits(-5) = 4*            howManyBits(0)  = 1*            howManyBits(-1) = 1*            howManyBits(0x80000000) = 32*  Legal ops: ! ~ & ^ | + << >>*  Max ops: 90*  Rating: 4*/
int howManyBits(int x) {int temp = x ^ (x << 1);int bit_16,bit_8,bit_4,bit_2,bit_1;bit_16 = !!(temp >> 16) << 4;temp = temp >> bit_16;bit_8 = !!(temp >> 8) << 3;temp = temp >> bit_8;bit_4 = !!(temp >> 4) << 2;temp = temp >> bit_4;bit_2 = !!(temp >> 2) << 1;temp = temp >> bit_2;bit_1 = !!(temp >> 1);return 1 + bit_1 + bit_2 + bit_4 + bit_8 + bit_16;
}
/* * isNonZero - Check whether x is nonzero using*              the legal operators except !*   Examples: isNonZero(3) = 1, isNonZero(0) = 0*   Legal ops: ~ & ^ | + << >>*   Max ops: 10*   Rating: 4 */
int isNonZero(int x) {int ret = ~x + 1;  ret = ret | x;       return (ret >> 31) & 1;
}
/** isPower2 - returns 1 if x is a power of 2, and 0 otherwise*   Examples: isPower2(5) = 0, isPower2(8) = 1, isPower2(0) = 0*   Note that no negative number is a power of 2.*   Legal ops: ! ~ & ^ | + << >>*   Max ops: 20*   Rating: 4*/
int isPower2(int x) {int y = x+(~1)+1;return !(x&y) & !(x>>31) & !!x;
}

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

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

相关文章

初学vue3与ts:vue3选项式api获取当前路由地址

vue2的获取方法 this.$route.pathvue3选项式api获取方法 import { useRouter } from vue-router; const router useRouter(); console.log(router) console.log(router.currentRoute.value.path)

测开速成考点

用户登录界面需要做哪些测试&#xff1f; ⑴功能&#xff1a;  正确的用户名&#xff0c;正确的密码&#xff0c;点击提交按钮&#xff0c;验证能否正确登录 是否跳转正确页面。  错误的用户名 或 密码&#xff0c;点击提交&#xff0c;提示相应的错误信息。  记住用户名…

Word文件设置了只读模式,为什么还能编辑?

Word文档设置了只读模式&#xff0c;为什么还可以编辑呢&#xff1f;&#xff0c;不过当我们进行保存的时候会发现&#xff0c;word提示需要重命名并选择新路径才能够保存&#xff0c;是因为什么呢&#xff1f;今天我们学习一下如何解决问题。 这种操作&#xff0c;即使可以编辑…

Python-文件详解

一个计算机包括&#xff1a;CPU、存储器、输入设备、输出设备 存储器分为内存和硬盘 文件路径&#xff1a;一层一层文件目录组成的字符串 文件路径可以视为文件在硬盘中的身份标识&#xff0c;因为每一个文件的1路径唯一 文件之间使用/反斜杠和\正斜杠都一样 内存和硬盘的区别…

AI文本生成工具-免费AI文本生成软件

在当今数字时代&#xff0c;人工智能技术的快速发展不仅改变了我们的生活方式&#xff0c;还在创作领域崭露头角。其中&#xff0c;AI文本生成技术的迅猛发展引起了广泛关注。本文将深入探讨AI文本生成的方法、工具以及一些关键技巧&#xff0c;帮助读者更好地了解并利用这一前…

Run Micro-ROS on almost any stm32

Run Micro-ROS on almost any stm32 - Tech blog (guillaumebeuzeboc.github.io) Run Micro-ROS on almost any stm32 19 Sep 2021 c, cmake, stm32, micro-ros, clion 如果用的不是STM32F4&#xff0c;需要自己去生成micro_ros_stm32cubemx_utils库 Micro-ROS brings the…

UNIX 文件权限设置的相关函数

函数 umask umask 函数为进程设置文件模式创建屏蔽字&#xff0c;并返回之前的值。这个函数没有出错返回&#xff0c;它不会出错. #include <sys/stat.h> mode_t umask(mode_t cmask); // 返回值&#xff1a;为文件模式创建屏蔽字 其中&#xff0c;参数 cmask 是由 文…

qt 5.15.2 主窗体菜单工具栏树控件功能

qt 5.15.2 主窗体菜单工具栏树控件功能 显示主窗体效果&#xff1a; mainwindow.h文件内容&#xff1a; #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QFileDialog> #include <QString> #include <QMessageBox>#inc…

m1通过源码编译xgboost4j的jar

1、下载源码 git clone --recursive https://github.com/dmlc/xgboost cd xgboost 编译xgboost的动态链接库dylib&#xff0c;m1源码编译xgboost的动态链接库dylib文件 2、编译XGBoost的jar文件&#xff1a; A、如果没有安装maven可以通过以下命令进行安装&#xff0c;如果安…

【开发技能】-解决visio交叉线(跨线)交叉点弯曲问题

问题 平时工作中使用visio作图时&#xff0c;经常会遇到交叉线在相交时会形成一个弯曲弓形&#xff0c;这十分影响视图效果。可以采用下面的方法消除弓形。 方法 第一步&#xff1a;菜单栏--设计---连接线 第二步&#xff1a;选中这条交叉线---点击显示跨线 最终问题得到解决…

基于ssm学校运动会信息管理系统论文

摘 要 在当今社会上&#xff0c;体育运动越来越普及&#xff0c;参与运动会的人越来越多&#xff0c;但是目前对运动会信息管理还是处于手工记录的时代&#xff0c;这远远满足不了现在用户需求&#xff0c;因此建立一个运动会信息管理系统已经变的非常重要。 本文重点阐述了学…

16个UI设计小规则,但是却能产生巨大影响

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版&#xff0c;欢迎购买。点击进入详情 文章目录 1.使用空间对相关元素进行分组2.保持一致3.确保外观相似的元素功能相似4.创建清晰的视觉层次5.删除不必要的样式6.有目的地使用颜色7.确保界面元素的对比…

漫步者开放式耳机怎么样?南卡、漫步者开放式耳机哪个好?

现在开放式耳机的市场越来越混杂&#xff0c;我们作为消费者在挑选的时候&#xff0c;一定要找准需求点才能把踩坑几率降到最低。实在不会挑选的也不要紧&#xff0c;我最近入了2款目前市面最畅销的百元款开放式耳机&#xff1a;南卡OE CC和漫步者comfo fit&#xff0c;亲身上耳…

resnet 图像分类的项目

1. 项目文件 文件下载资源&#xff1a;resnet 图像分类的项目代码 本章利用reset34 作图像分类&#xff0c;包括计算训练集和测试集的loss、accuracy曲线&#xff0c;对训练好的网络在训练集测试集上求混淆矩阵 data 文件为训练集测试集&#xff0c;图像按照文件夹摆放inferenc…

55.MQ高级特性

目录 一、RabbitMQ部署指南。 1&#xff09;单机部署。 1.1.下载镜像 1.2.安装MQ 2&#xff09;安装DelayExchange插件。 2.1.下载插件 2.2.上传插件 2.3.安装插件 2.4.使用插件。 3&#xff09;集群部署。 3.1.集群分类 3.2.获取cookie 3.3.准备集群配置 3.4.启…

MATLAB将动画演示以及将过程保存为gif动态图片

平时想要做一个动画图片来演示&#xff0c;本人一般有两种方法&#xff1a; 一种是截很多张图之后&#xff0c;将这些图片合成为一张gif动画&#xff1b; 另一种就是录屏再制作成gif&#xff0c;我一般是录下视频之后&#xff0c;使用QQ影音&#xff0c;里面的影音工具箱有一个…

2021年度大题:灰太狼的密码

分析&#xff1a;本题主要使用的是素数进行输出&#xff0c;然后难点是如何按照题目要求格式输出。 思路&#xff1a; 第一&#xff1a;我们可以先让素数存给一个一维数组&#xff0c;至于存多少个素数&#xff0c;是矩阵n*n个&#xff0c;控制数量用计数器count即可&#xf…

汽车电子 -- CAN文件格式ASC

Vector提供了两种记录数据格式的格式规范&#xff1a;BLF和ASC。 先讲讲ASC。 参看&#xff1a;图文详解CAN Log文件 - ASC文件格式 一、ASC文件格式 在Vector提供的 CAN_LOG_TRIGGER_ASC_Format.pdf 提取码&#xff1a;ltjv 文件中&#xff0c;规定了CANoe/CANalyzer ASC记…

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之linux存储管理(3)》(19)

《Linux操作系统原理分析之linux存储管理&#xff08;3&#xff09;》&#xff08;19&#xff09; 6 Linux存储管理6.4 Linux 的分段和分页结构6.4.1Linux 的分段结构6.4.2 Linux 的三级分页结构6.4.3 内核页表和进程页表 6 Linux存储管理 6.4 Linux 的分段和分页结构 本节主…

微服务实战系列之Redis

前言 云淡天高&#xff0c;落木萧萧&#xff0c;一阵西北风掠过&#xff0c;似寒刀。冬天渐渐变得更名副其实了&#xff0c;“暖冬”的说法有点言过其实了。——碎碎念 微服务实战系列之Cache微服务实战系列之Nginx&#xff08;技巧篇&#xff09;微服务实战系列之Nginx微服务实…