西工大计算机学院计算机系统基础实验一(函数编写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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

轨迹分析:Palantir评估细胞分化潜能 类似于monocle2

轨迹分析是单细胞测序分析中重要的组成部分&#xff0c;它基于细胞谱系之间“具有中间态细胞”的理论基础&#xff0c;通过结合先验知识&#xff08;细胞注释、markers&#xff09;、细胞基因表达改变等&#xff0c;为在单细胞测序数据赋予了“假时间”&#xff08;pseudotime&…

vscode eide arm-gcc 编译环境搭建调试

安装cube&#xff0c;vscode 1.安装vscode插件 C/C Extension Pack Chinese (Simplified) (简体中文) Language Pack Cortex-Debug Embedded IDE 工具链设置 2.软件工程生成 调试 3.生成工程&#xff0c;导入工程 4. 配置工程 编译完毕

【EI会议征稿】第五届大数据与信息化教育国际学术会议(ICBDIE 2024)

【往届检索】第五届大数据与信息化教育国际学术会议&#xff08;ICBDIE 2024&#xff09; 2023 5th International Conference on Big Data and Informatization Education 第五届大数据与信息化教育国际学术会议&#xff08;ICBDIE 2024&#xff09;定于2024年01月19-21日在…

小型洗衣机哪个牌子质量好?内衣洗衣机便宜好用的牌子

近些年来&#xff0c;由于人们对生活和健康的追求越来越高&#xff0c;所以内衣洗衣机也逐渐走进了人们的视线&#xff0c;许多研究显示&#xff0c;单纯地用手洗内衣是并不能彻底消除内衣物上所残留的细菌&#xff0c;而内衣洗衣机拥有着高温蒸煮的除菌功能&#xff0c;因此可…

【C语言】用户空间使用非缓存内存

在用户空间使用非缓存内存通常不是标准做法&#xff0c;因为非缓存内存的操作与硬件平台紧密相关&#xff0c;并且通常被保留给内核模块或设备驱动程序使用。 一、方法 用户空间程序一般不直接处理非缓存内存问题&#xff0c;因为它们依赖于操作系统来管理内存缓存一致性。尽…

智慧景区(园区)数字孪生可视化GIS解决方案

随着技术的日新月异&#xff0c;景区日常管理及运营中使用到的智慧化工具越来越丰富&#xff0c;智慧化硬件设备也越来越多&#xff0c;而其中各个管理系统往往又是相互独立&#xff0c;形成一个个数据孤岛。智慧景区管理平台就是将各个孤岛中的数据及功能汇集起来&#xff0c;…

叮!速来get宏基因组元素循环耦合分析!

微生物通过一系列氧化还原反应驱动生物地球化学循环&#xff0c;有的微生物可以耦合不同元素的生物地球化学循环&#xff0c;例如碳、氮、磷、硫等&#xff0c;存在复杂的耦合关系。 图 升高(A)和气候变暖(B)对氮库和转化过程影响的概念图 红树林生态系统被认为是生物地球化学…

Elasticsearch:什么是大语言模型(LLM)?

大语言模型定义 大语言模型 (LLM) 是一种深度学习算法&#xff0c;可以执行各种自然语言处理 (natural language processing - NLP) 任务。 大型语言模型使用 Transformer 模型&#xff0c;并使用大量数据集进行训练 —— 因此规模很大。 这使他们能够识别、翻译、预测或生成文…

HASH 哈希算法之MD5 算法

1. 哈希算法&#xff0c;用C 写的 #include <iostream> #include <iomanip> #include <cstring> #include <openssl/md5.h> #include <stdio.h>using namespace std;int main() {string str "hello world";unsigned char digest[MD5…

网络安全(一)--网络环境构成,系统的安全

2. 网络攻防环境 目标 了解攻防环境构成了解入侵检测系统&#xff08;平台&#xff09;的部署位置 2.1. 环境构成 2.1.1. 环境框图 一个基本的网络攻防实验环境包括&#xff1a;靶机、攻击机、入侵检测分析系统、网络连接四部分组成。 一个基础的网络攻防实验环境需要如下…

【c语言指针详解】指针的高级应用

目录 一、指针和字符串 1.1 字符串和字符数组的关系 1.2 字符串常量和字符指针的使用 1.3 字符串函数库的指针参数 1.3.1 strlen 函数 1.3.2 strcpy 函数 1.3.3 strcat 函数 1.3.4 strcmp 函数 二、指针的高级应用 2.1 函数指针的定义和使用 2.2 回调函数和函数指针数组的应用 …

2022年第十一届数学建模国际赛小美赛D题野生动物贸易是否应长期禁止解题全过程文档及程序

2022年第十一届数学建模国际赛小美赛 D题 野生动物贸易是否应长期禁止 原题再现&#xff1a; 野生动物市场被怀疑是此次疫情和2002年SARS疫情的源头&#xff0c;食用野生肉类被认为是非洲埃博拉病毒的一个来源。在冠状病毒爆发后&#xff0c;中国最高立法机构永久性地加强了野…

基于SpringBoot的大学活动平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着互联网技术的不断…

如何统计12.5米高程覆盖率?

无论是卫星影像还是高程DEM数据&#xff0c;覆盖率都是大家非常关心的一个重要参数。 我们曾基于WGS84坐标进行过简单的覆盖率计算&#xff0c;而且面积还包括了海洋区域。 因此&#xff0c;最后得出了一个非常不靠谱&#xff0c;看起来也很不漂亮的数据&#xff1a;12%。 为…

【算法】对二分搜索的理解

二分搜索大家都很熟悉&#xff0c;首先我们先来看看基本框架 func binarySearch(nums []int, target int) int {left, right : 0, ...for ... {mid : left (right-left)/2if nums[mid] target {...} else if nums[mid] < target {left ...} else if nums[mid] > targ…

快速安装Axure RP Extension for Chrome插件

打开原型文件的html&#xff0c;会跳转到这个页面&#xff0c;怎么破&#xff1f; 我们点开产品设计的原型图如果没有下载Axure插件是打不开&#xff0c;而我们国内网通常又不能再google商店搜索对应插件&#xff0c;下面教大家如何快速安装 1、打开原型文件->resources-&g…

星钻图形输出

答案&#xff1a; #include <stdio.h> int a 0, b 0; void printLine(int a , int b) //输出一行包含&#xff1a;若干个空格 若干个*&#xff0c;第一&#xff0c;二个参数为空格数和*数&#xff1b; (定义一个星钻输出函数) {while (a--) //打印a个空格{printf(…

内衣洗衣机和手洗哪个干净?高性价比内衣洗衣机推荐

通常来说&#xff0c;我们的内衣裤对卫生要求比较高&#xff0c;毕竟是贴身穿的&#xff0c;所以如果和一般的衣物一起洗&#xff0c;就怕会有细菌互相感染。所以很多用户为了内衣裤的卫生都会选择自己手动洗&#xff0c;但手洗一方面很费时间和人力&#xff0c;另一方面又很伤…

el-menu标题过长显示不全问题处理

项目基于vue-element-admin 问题 期望 处理方式 \src\layout\components\Sidebar\index.vue 文件后添加CSS <style scped> /* 侧栏导航菜单经典 文字超长溢出问题 CSS折行 */ .el-submenu__title {display: flex;align-items: center; } .el-submenu__title span {white-…

刚毕业做前端开发难度会很大吗

这里是up主的三段经历&#xff0c;小伙伴们可以自己看一看 首先可以确定的是&#xff0c;不是很大&#xff0c;因为如果你能走到做开发这一步去&#xff0c;说明你的基础能力是够硬的 我的第一段经历&#xff0c;也就是我的第一份实习&#xff0c;是一家小企业&#xff0c;一共…