函数递归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>>结语

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

        

  • 33
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值