首页 > 其他分享 >函数递归VS操作符深入?

函数递归VS操作符深入?

时间:2024-08-16 17:22:42浏览次数:14  
标签:0000 递归 补码 1111 VS 操作符 阶乘 按位 原码

1>>前言

        函数递归函数递归,当小白听到这样的词会感到无比陌生,请不要惊慌,这是正常的,以至于都不是很经常用到,但是它的算法,它的思想是值得我们深入思考的。还有一些复杂操作符,如按位与按位或等等,今天一并说说,希望大家能学到东西

2>>函数递归

        函数的递归分为递推与回归,就是将一个重复的事情逐渐化小,这就叫递推,类似于高等数学的微分,回归就是将缩小的事情再放大,这就是回归,类似于积分。这里我们给出一个题目,输入一个数,使用函数递归求出该数阶乘。我们借助题目能更好理解递归的概念。

2.1>>附:阶乘概念

        首先我们需要知道,阶乘是从1开始逐步乘到需要的数,如5的阶乘就是1*2*3*4*5。3的阶乘就是1*2*3,用3!表示,6的阶乘就用6!表示。一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数n的阶乘写作n!。1808年,基斯顿·卡曼引进这个表示法。亦即n!=1×2×3×...×(n-1)×n。

2.2>>递推

        在我们了解了阶乘的概念后,我们就可以引入递推了,将大事化小,如5的阶乘可以写作5*4!而4的阶乘可以写作4*3!这里以此类推,可以发现n!=n*n(-1)!那么我们将它代入函数就可以做到递推,这边看代码,然后我放一张图具体解释同学们就懂了。

#include<stdio.h>
//题目:输入一个数,使用函数递归求出该数的阶乘。 

int Fact(a)
{
	if (a<=0) 
		return 1;
	else
		return a*Fact(a-1);
}

int main()
{
	int a=0;
	scanf("%d",&a);
	int c=Fact(a);
	printf("%d\n",c);
	return 0;
}

 这里我们计算5的阶乘为例子,a=5进入Fact函数,因为a>0所以进入else语句

​这里5进来又遇到了函数Fact,此时把4代入以此类推,直到a=0开始返回数值。

2.3>>回归

        开始返回值时并不是一下子返回到主函数,而是像前面的递推一样,一步步回归

先从1返回到上一步执行的函数,相当于1*0!,而0的阶乘又是1,所以相当于1*1

接下来又返回1,而此时a是2,相当于2*1的阶乘,以此类推我们可以得到

5的阶乘为120,这就是函数的递归。

2.4>>个人感觉

        函数的递归在C语言中并不是很常用,主要还是使用迭代,也就是循环,当然递归我也感觉很神奇,很多题目我都想尝试使用递归去做,但我现在能力还不够,也可能是递归只有在一些特定场景下才能使用,才能发挥它的无穷力量!

3>>操作符的深入

        操作符这边会讲到按位与&,按位或|,按位异或^,还有按位取反~的用法。

3.1>>补充:进制转换

        首先我们需要知道十进制如何转换为二进制的,十进制整数转换为二进制整数采用"除2取余,逆序排列"法。具体做法是:用2整除十进制整数,可以得到一个商和余数;再用2去除商,又会得到一个商和余数。如此进行,直到商为小于1时为止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列起来。如13,我们除2得到6余1,6除2得到3余0,3除2得到1余1,最后余1,然后将余数逆序排列得到1101这就是13的二进制数。

要进行转换也很简单二进制数1111每个代表的分别是8421,每往左边一个1就乘2,若10000这个1就代表16。而1101就是对应十进制数相加,就是8+4+1=13.

3.2>>补充:原码、反码、补码的概念 

        知道了进制转换现在我们就可以知道13的原码(这边注意正数原码反码补码三者相同,负数反码按位取反(取反的意思就是0为1,1为0),补码则为反码+1)13的原码为:0000 0000 0000 0000 0000 0000 0000 1101,这里要32位二进制数,代表整形四个字节,那么再举一个例子(这里注意正负数的二进制位第一位为符号位,1为负数,0为正数

-1的原码为:1000 0000 0000 0000 0000 0000 0000 0001

-1的反码为:0111 1111 1111 1111 1111 1111 1111 1110

-1的补码为:0111 1111 1111 1111 1111 1111 1111 1111

到这里,大家对原码反码补码的概念应该清楚一点了。接下来讲解操作符。

3.3>>按位与&,按位或|,按位异或^,按位取反~

        按位与&的用法就是两1为1,其余情况为0,如101 & 111 结果就是 101,可以理解为:多选题,全选对了则是对。

        按位或|的用法就是有一个1就是1,两0才为0,如100 | 001 结果就是101,可以理解为:我现在是个渣男/渣女,需要买一个金戒指,不管备胎一号出钱还是备胎二号出钱,只要有一个出钱我都能买到,哈哈哈这就是按位或。

        按位异或^的用法就是相同则0,不同则1,如111 ^ 001 结果就是110,可以理解为:抄作业,你抄我的我两答案都一样,OMG的雷同卷,判0分,我们一起g了,所以相同为0,不同为1。

        按位取反比较简单,~111 结果就是000。

3.4>>巩固知识

理清了它们的概念我们就来做一下题目巩固一下知识:输入一个数,计算该数转换为二进制后有多少个1。

#include<stdio.h>
//输入一个数,计算该数转换为二进制后有多少个1
int main()
{
	int a=0;
	int count=0;
	scanf("%d",&a);
	while(a)
	{
		a=a & (a-1);
		count++; 
	}
	printf("%d\n",count);
	return 0;
}

这里来解析一下代码(注意运算都是用该数的补码运算):假设我们的a是13它的原码反码补码相同为0000 0000 0000 0000 0000 0000 0000 1101,a-1为0000 0000 0000 0000 0000 0000 0000 1100,此处省略前面的0,来对比1101和1100,这两个逻辑与结果就是1100,在循环,1100和1100-1即1011逻辑与又得到1000,这样每次逻辑与完都去掉最右边的一个1,简直妙哉,最终a为0退出循环,打印结果。

这时就有人说了,例子都是正数,能不能来个负数,好的安排!


这里可以看到结果为32个1,为什么呢?不急我们先来看看-1的原码反码补码:

-1的原码为:1000 0000 0000 0000 0000 0000 0000 0001

-1的反码为:0111 1111 1111 1111 1111 1111 1111 1110

-1的补码为:0111 1111 1111 1111 1111 1111 1111 1111

注意:补码取反加一也能得到原码

使用补码进行计算,-1的结果为:0111 1111 1111 1111 1111 1111 1111 1110逻辑与完就是0111 1111 1111 1111 1111 1111 1111 1110,以此类推我们能得到31次运算,最后是32个0,取反加一再来一次运算就是32了,是不是很神奇!

4>>结语

        今天带来的是递归和操作符部分的深入讲解,函数递归在未来学算法估计会经常用到,原码反码补码对于未来学单片机和嵌入式的同学也很有帮助,另外:把自己所学的知识分享给大家,可以说是非常的舒服,感觉心灵受到了浇灌。小编要学习的地方还有很多,请大家多多指教,谢谢大家!

        

标签:0000,递归,补码,1111,VS,操作符,阶乘,按位,原码
From: https://blog.csdn.net/m0_69282950/article/details/141262453

相关文章

  • VScode踩坑记录
    #2024.8.15以来的VScode踩坑记录引言        本文仅作为本人对初次配置VScode环境的记录,不具备通用性。        自8.15进组以来,领到的第一个任务是安装VScode,之后将师兄师姐原先程序在自己的电脑上运行起来。VScode安装与C/C++环境配置        下......
  • 五、1 算数操作符&位操作符
    1、算数操作符(1)“/”得到一个整数商,不包含余数进行浮点数除法,操作符两端至少有一个浮点数(2)“%”取模,得到余数两端必须为整数2、位操作符(只适用于整型)(1)“&”按位与,有0为0,全为1则为1;(2)“|”按位或,有1为1,全为0则为0;(3)“^”按位异或,相同为0,相异为1.在十进制中异或,a......
  • 递归
    packagecom.shujia.day16.ketang;/*递归:方法定义时方法内部调用自身的现象。区分:Math.max(Math.max(10,20),30)方法的嵌套调用StringBuffer.append().append().append()方法的链式调用讲故事:故事1:从前有座山,山里有座庙,庙里有......
  • C语言中的操作符:深入解析与应用
    引言C语言提供了丰富的操作符,用于执行算术运算、逻辑判断、位操作等。这些操作符是编程语言中的基础构件,它们使得程序能够进行复杂的数据处理和逻辑控制。本文将详细介绍C语言中的各种操作符,包括它们的类型、用法和一些实际应用示例。操作符的分类算术操作符算术操作符用于......
  • 在C/C++中嵌入Lua代码及使用VS Code调试
     Lua在设计之初就是为了嵌入到应用程序中,为这些应用程序提供灵活的扩展和定制功能。Lua的核心是用C语言编写的,所以Lua脚本可以很容易地与C/C++代码进行交互,通过Lua脚本,用户可以在不修改原有C/C++代码的基础上,实现功能的扩展和定制。 在C/C++程序中可以使用Lua来编写一些需......
  • 基于价值流DevSecOps效能案例介绍
    背景    数字经济时代,企业数字化转型加速,软件业务收入目标设定,产业基础保障水平提升。DevSecOps:作为解决交付能力挑战的方法,强调开发(Dev)、安全(Sec)、运维(Ops)的整合。DevSecOps持续发布流水线通过两种发布快速通路实现质量效率的均衡,一种是以自动Q点(质量检查点)检查快速上线方......
  • JAVA8 stream 流 vs JDFrame (转)
    转自: https://juejin.cn/post/7356652717392740404个人开源框架矩阵百万级任务重试框架Fast-Retrystream流太难用了看看JDFramespring-smart-di动态切换实现类框架UniHttp第三方接口对接框架0、简介由于经常记不住stream的一些API每次要复制来复制去并且又长又臭,想要更......
  • 序列建模之循环和递归网络 - 双向RNN篇
    序言在序列建模的广阔领域中,循环神经网络(RNN\text{RNN}RNN)以其独特的循环结构,在处理序列数据方面展现出了强大的能力。然而,传统的单向......
  • 在K8S中,Kube-Proxy为什么使用ipvs,而不使用iptables?
    Kubernetes中的kube-proxy是负责实现服务(Services)负载均衡的核心组件之一。它支持两种主要的代理模式:iptables模式和ipvs模式。这两种模式都可以用来实现服务的网络流量转发,但它们之间存在一些关键的区别。1.为什么使用ipvs而不是iptables?性能优势:连接跟踪:ipvs直......
  • 递归与回溯
    递归1.含义递归:函数(方法)直接或间接调用自身2.调用过程如果递归调用没有终止,将会一直消耗栈空间最终导致栈内存溢出(StackOverflow)所以必需要有一个明确的结束递归的条件也叫作边界条件、递归基 3.基本思想1.拆解把规模大的问题变成规模较小的......