C语言之linux内核--BCD码转二进制与二进制转BCD码(笔试经典)

在分析代码之前,我们先来了解一下,BCD码和二进制到底区别在哪?

      学习过计算机原理的和数字电子技术这两门课的都会知道这两个到底是什么含义,也有的同学学过了,考过了,过了一段时间又忘记了,今天,我们通过一个代码案例来说说:

     我们先查查百度,了解一下BCD码:

BCD码(Binary-Coded Decimal‎)亦称二进码十进数或二-十进制代码。用4位二进制数来表示1位十进制数中的0~9这10个数码。是一种二进制的数字编码形式,用二进制编码的十进制代码。BCD码这种编码形式利用了四个位元来储存一个十进制的数码,使二进制和十进制之间的转换得以快捷的进行。这种编码技巧最常用于会计系统的设计里,因为会计制度经常需要对很长的数字串作准确的计算。相对于一般的浮点记数法,采用BCD码,既可保存数值的精确度,又可免去使电脑作浮点运算时所耗费的时间。此外,对于其他需要高精确度的计算,BCD编码亦很常用。

由于十进制数共有0、1、2、……、9十个数码,因此,至少需要4位二进制码来表示1位十进制数。4位二进制码共有2^4=16种码组,在这16种代码中,可以任选10种来表示10个十进制数码,共有N=16!/[10!*(16-10)!]等于8008种方案。常用的BCD代码列于末。

BCD码可分为有权码和无权码两类:有权BCD码有8421码、2421码、5421码,其中8421码是最常用的;无权BCD码有余3码,余3循环码等。

BCD码的运算规则:BCD码是十进制数,而运算器对数据做加减运算时,都是按二进制运算规则进行处理的。这样,当将
BCD码传送给运算器进行运算时,其结果需要修正。修正的规则是:当两个BCD码相加,如果和等于或小于 1001(即十进制数9),不需要修正;如果相加之和在
1010 到1111(即十六进制数 0AH~0FH)之间,则需加 6 进行修正;如果相加时,本位产生了进位,也需加 6 进行修正。这样做的原因是,机器按二进制相加,所以
4 位二进制数相加时,是按“逢十六进一”的原则进行运算的,而实质上是
2 个十进制数相加,应该按“逢十进一”的原则相加,16 与10相差 6,所以当和超过 9或有进位时,都要加 6 进行修正。

有点哆嗦,接下来我们直接来看看代码:

#include <stdio.h>
#include <stdlib.h>
//BCD码转为二进制
unsigned bcd2bin(unsigned char val)
{
	return (val & 0x0f) + (val >> 4) * 10;
}

//二进制转为BCD码
unsigned char bin2bcd(unsigned val)
{
	return ((val / 10) << 4) + val % 10;
}

int main(void)
{
	unsigned  val =  17;
	printf("bin:%u--->0x%x\n",val,val);
	printf("bcd:%u--->0x%x\n",bin2bcd(val) , bin2bcd(val));
	return 0 ;
}

运行结果:

从结果可以看出17的二进制数是0001 0001---->对应16进制0x11

将17转为BCD码后4个位表示一个位,所以就表示为二进制数0001 0111----->对应16进制数0x17也就是十进制的23

总结:

BIN码:就是二进制数 

BCD码:原则是从低位开始分别以四个Bit表示一个位,BCD码就是十进制的二进制数

另外一个BCD码转二进制接口不尝试,原理一样。

时间: 2024-10-15 04:08:12

C语言之linux内核--BCD码转二进制与二进制转BCD码(笔试经典)的相关文章

C语言之linux内核实现最大公约数算法

最大公约数算法,又称欧几里德算法,至今已有几千年的历史了.在我们开始学习C语言的时候最常用的算法就是辗转相除法,其实在linux内核中,内核也是使用这样的方法实现两数最大公约数的计算.      两个整数的最大公约数是能够同时整除它们的最大的正整数.辗转相除法基于如下原理:两个整数的最大公约数等于其中较小的数和两数的相除余数的最大公约数.       例如,252和105的最大公约数是21(252 = 21 × 12:105 = 21 × 5);       算法原理: 设两数为a.b(b<a)

C语言之linux内核实现位数高低位互换

linux内核实在是博大精深,有很多优秀的算法,我之前在工作中就遇到过位数高低位交换的问题,那时候对于C语言还不是很熟练,想了很久才写出来.最近在看内核的时候看到有内核的工程师实现了这样的算法,和我之前想的一样,那么今天就把它分享出来吧.       在开发需求中,有要实现32位.16位.8位数高低位交换的算法.那么我们具体看看代码实现: 还是一样,从linux内核中将代码抠出来: #include <stdio.h> //将一个8位数高低4位交换 static inline unsigned

C语言之linux内核可变参实现printf,sprintf

      昨天,我发表了一篇用可变参实现的fprintf函数,其实说实话还不完全是可变参实现的,因为用到了FILE * 这样的指针,需要包含stdio.h这个头文件才能实现这个函数,今天我们就来看看,如何抛弃stdio.h,全0开始实现printf , sprintf ,当然,这段代码是我在linux内核里面获取的,再经过我本人修改,移植,在DevC++这个编译环境中通过测试.我们来看看代码:       #include <stdarg.h> #define NULL 0 //如果字符串中

C语言在linux内核中do while(0)妙用之法

为什么说do while(0) 妙?因为它的确就是妙,而且在linux内核中实现是相当的妙,我们来看看内核中的相关代码: #define db_error(fmt, ...) \ do { \ fprintf(stderr, "(error): "); \ fprintf(stderr, fmt, ##__VA_ARGS__); \ } while (0) 这只是个普通的调试信息的输出,有人便会认为,你这不是多此一举吗?去掉do while(0)不一样也实现了吗?其实不然,我们看看例子

C语言之linux内核实现平方根计算算法

关于平方根的计算,在linux内核中也有实现,就像math.h数学库里的sqrt这个函数一样.       平方根的公式定义: 如果一个非负数x的平方等于a,即    ,    ,那么这个非负数x叫做a的算术平方根.a的算术平方根记为    ,读作"根号a",a叫做被开方数(radicand).求一个非负数a的平方根的运算叫做开平方.结论:被开方数越大,对应的算术平方根也越大(对所有正数都成立). 一个正数如果有平方根,那么必定有两个,它们互为相反数.显然,如果我们知道了这两个平方根的

《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #2 如何编译Linux内核

HACK #2 如何编译Linux内核 本节介绍编译Linux内核的方法. 当发现bug而修改源代码或者添加新功能时,就需要对内核进行重新编译,生成二进制映像文件.另外,如果想要使用发布版内核中无效的功能或者驱动程序时,或者相反地,想要删除不需要的功能从而使内核更精简.更快时,或者想使用最新版的上游内核时,也需要对内核进行编译. 下面主要介绍对上游内核进行设置.编译以及安装的方法.当使用发布版内核的源码包管理系统来管理内核映像文件时,需要将内核映像文件打包.接下来以两个具有代表性的发布版Fedo

Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7) 【转】

原文地址:Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7) 作者:tekkamanninja  转自:http://blog.chinaunix.net/uid-25909619-id-4938390.html   在构架相关的汇编代码运行完之后,程序跳入了构架无关的内核C语言代码:init/main.c中的start_kernel函数,在这个函数中Linux内核开始真正进入初始化阶段,      下面我就顺这代码逐个函数的解释,但是这

linux内核中的C语言常规算法(前提:你的编译器要支持typeof和type)

学过C语言的伙伴都知道,曾经比较两个数,输出最大或最小的一个,或者是比较三个数,输出最大或者最小的那个,又或是两个数交换,又或是绝对值等等,其实这些算法在linux内核中通通都有实现,以下的代码是我从linux内核源码的kernel.c中抠出来的代码,我们来看看: 我们直接上代码: #include <stdio.h> #include <stdlib.h> /* * min()/max() macros that also do * strict type-checking..

【lLinux驱动】linux内核源码目录结构

linux内核源码目录结构 代码目录结构  在阅读源码之前,还应知道Linux内核源码的整体分布情况.现代的操作系统一般由进程管理.内存管理.文件系统.驱动程序和网络等组成.Linux内核源码的各个目录大致与此相对应,其组成如下(假设相对于Linux-2.4.23目录):  arch目录包括了所有和体系结构相关的核心代码.它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel CPU及与之相兼容体系结构的子目录.PC机一般都基于此目录.  include目录包括编译核