文章目录

  • 简介
  • 进制的基本概念
  • 二进制、八进制、十六进制加减法的区别
    • 二进制
    • 八进制
    • 十六进制
  • 数制之间的转换
    • 情景一、将二进制、八进制、十六进制转换为十进制(总结:按权相加)
      • 整数部分(不带小数)
      • 整数部分+小数部分
    • 情景二、将十进制转换为二进制、八进制、十六进制(总结:整数部分为除 N 取余,逆序排列,小数部分为乘 N 取整,顺序排列,N为要转换对应进制的基数)
      • 整数部分(不带小数)
      • 整数部分+小数部分
    • 情景三、二进制和八进制、十六进制的转换(总结:通常二进制的3位分别用八进制的3位和十六进制的4位来表示)
      • 二进制整数和八进制整数之间的转换
      • 二进制整数和十六进制整数之间的转换

简介

目前计算机虽然能够快速运算,但它内部使用的数据并不像人类所熟悉的十进制数,而是使用只含0、1组成的二进制数。我们输入到计算机的十进制数需要被转换成二进制数后再进行计算,计算后的结果又由二进制转换成我们需要的进制数,这些都是由操作系统自动完成,数制是用一组固定的符号和统一的规则来表示数值的方法,人们通常采用的数制有十进制,二进制,八进制和十六进制。

进制的基本概念

二进制,八进制,十进制,十六进制之间的区别在于:

  • 数码(各个位上的数字)表示的范围不同,二进制的数码有0和1,十六进制的数码有0~9,A~F
  • 基数(所能够使用数码的个数)不同,二进制的基数为2,十六进制的基数为16
  • 位权(i位上的位权为基数的(i-1)次幂,从左至右分别为第1位,第2位…),如十进制数123中的1所在位的位权是10^2,2所在位的位权是10^1,3所在位的位权是10^0;二进制数1101中,最左边的1位权是2^3

二进制、八进制、十六进制加减法的区别

二进制

二进制加减法和十进制加减法的思想是类似的:对于二进制,进行加法运算时逢二进一,进行减法运算时借一当二。

  • 二进制加法:1+0=1、1+1=10、11+10=101、111+111=1110
  • 二进制减法:1-0=1、10-1=1、101-11=10、1100-111=101

八进制

八进制有 0~7 共8个数字,基数为8,加法运算时逢八进一,减法运算时借一当八。例如,数字 0、1、5、7、14、733、67001、25430 都是有效的八进制。

  • 八进制加法:3+4=7、5+6=13、75+42=137、2427+567=3216

  • 八进制减法:6-4=2、52-27=23、307-141=146、7430-1451=5757

十六进制

十六进制中,用A来表示10,B表示11,C表示12,D表示13,E表示14,F表示15,因此有 0~F 共16个数字,基数为16,加法运算时逢16进1,减法运算时借1当16。例如,数字 0、1、6、9、A、D、F、419、EA32、80A3、BC00 都是有效的十六进制。

  • 十六进制加法:6+7=D、18+BA=D2、595+792=D27、2F87+F8A=3F11

  • 十六进制减法:D-3=A、52-2F=23、E07-141=CC6、7CA0-1CB1=5FEF

数制之间的转换

情景一、将二进制、八进制、十六进制转换为十进制(总结:按权相加)

二进制、八进制和十六进制向十进制转换都非常容易,就是“按权(位权)相加”。不清楚位权的同学可以往上看。
假设当前数字是 N 进制,那么:

  • 对于整数部分,从右往左看,第 i 位的位权等于Ni-1
  • 对于小数部分,恰好相反,要从左往右看,第 j 位的位权为N-j

整数部分(不带小数)

将二进制数字11010转换成十进制:

11010 = 1×2^4 + 1×2^3 + 0×2^2 + 1×2^1 + 0×2^0 = 26(十进制)

八进制数字 53627 转换成十进制:

53627 = 5×8^4 + 3×8^3 + 6×8^2 + 2×8^1 + 7×8^0 = 22423(十进制)

十六进制数字 9FA8C 转换成十进制(将A~F对应的具体的数字计算):

9FA8C = 9×16^4 + 15×16^3 + 10×16^2 + 8×16^1 + 12×16^0 = 653964(十进制)

整数部分+小数部分

二进制数字1010.1101 转换成十进制:

1010.1101 = 1×2^3 + 0×2^2 + 1×2^1 + 0×2^0 + 1×2^-1 + 1×2^-2 + 0×2^-3 + 1×2^-4 = 10.8125(十进制)

八进制数字 423.5176 转换成十进制:

423.5176 = 4×82 + 2×81 + 3×80 + 5×8-1 + 1×8-2 + 7×8-3 + 6×8-4 = 275.65576171875(十进制)

小数部分和整数部分相反,要从左往右看,第1位的位权为 8-1=1/8,第2位的位权为 8-2=1/64,第3位的位权为 8-3=1/512,第4位的位权为 8-4=1/4096 …… 第m位的位权就为 8-m。

C语言实现代码(仅讨论整数):

/*
将一个2,8进制转换为十进制 (算法思维从高位到低位运算,暂时没考虑16进制)
*/
#include <stdio.h>
#include <string.h>//strlen()
int OcToDec(char *a,int base);//将2,8进制数a转换为十进制数
int main(void)
{char a[20];//a存放八进制整数int tennum;//存放a对应的十进制整数printf("请输入一个数:") ;scanf("%s",a);//输入的时候,a[20]={1,0,1}  int n;printf("请输入该数的基数(输入的是几进制基数就是几):");scanf("%d",&n);tennum=OcToDec(a,n);printf("%d进制数%s转换为十进制为:%d\n",n,a,tennum);return 0;
}
int OcToDec(char *a,int base)
{int sum=0;//变量sum存放a对应的十进制数 int len=strlen(a);//位数 int weight=1;//位权值for(int i=len-1;i>=0;i--)//将八进制从低位向高位输出, 即数组a下标最大的元素为八进制的最低位 {sum+=(a[i]-'0')*weight;//数组下标i越小,即八进制位数越高,位权weight越重 ,a[i]-'0'转化为Ascii码运算到到一个字符数字对应的整型数字 weight*=base; } return sum;
}

测试输出:


扩展:以下代码块将int OcToDec(char *a,int base)函数体修改一下,让其从二进制或八进制高位向低位扫描各位上的数,按权相加求和。其中base为基数2或8

int OcToDec(char *a, int base)   //将base(8)进制数a转换成十进制数
{int sum = 0;              int len = strlen(a);    for(int i = 0;i < len;i++){  sum = sum * base + a[i] - '0';      }return sum;
}

情景二、将十进制转换为二进制、八进制、十六进制(总结:整数部分为除 N 取余,逆序排列,小数部分为乘 N 取整,顺序排列,N为要转换对应进制的基数)

将十进制转换为其它进制时比较复杂,整数部分和小数部分的算法不一样。如果一个数字既包含了整数部分又包含了小数部分,那么将整数部分和小数部分开,分别按照上面的方法完成转换,然后再合并在一起即可。

整数部分(不带小数)

具体做法:

  • 将 N (要转化的目标进制的基数) 作为除数,用十进制整数除以 N,可以得到一个商和余数;
  • 保留余数,用商继续除以 N,又得到一个新的商和余数;
  • 仍然保留余数,用商继续除以 N,还会得到一个新的商和余数;
  • 如此反复进行,每次都保留余数,用商接着除以 N,直到商为 0 时为止。

将十进制数字 36926 转换成八进制:

结果为110076(八进制)。

将十进制数字 42 转换成二进制的过程:

结果为101010(二进制)

整数部分+小数部分

具体做法:

  • 用 N(要转化的目标进制的基数) 乘以十进制小数,可以得到一个积,这个积包含了整数部分和小数部分;
  • 将积的整数部分取出,再用 N 乘以余下的小数部分,又得到一个新的积;
  • 再将积的整数部分取出,继续用 N 乘以余下的小数部分;
  • 如此反复进行,每次都取出整数部分,用 N 接着乘以小数部分,直到积中的小数部分为 0,或者达到所要求的精度为止。

十进制小数 0.930908203125 转换成八进制小数的过程:

十进制小数 0.930908203125 转换成八进制小数的结果为 0.7345。

十进制小数 0.6875 转换成二进制小数的过程:

十进制小数 0.6875 转换成二进制小数的结果为 0.1011。

C语言实现代码(仅讨论整数):

/*
将十进制转换为2,8,16进制
*/
#include <stdio.h>
#include <string.h>
void DToM(int d,int m,char *mnum);//D->decimalism
int main(void)
{int d;//存放输入的十进制数printf("请输入一个待转换的十进制数:"); scanf("%d",&d);int M;printf("请输入要转换的进制(2,8,16):");scanf("%d",&M);char Mnum[100];//存放十进制数d对应的M进制数DToM(d,M,Mnum);printf("该十进制数对应的%d进制数为:%s\n",M,Mnum); return 0;
}
void DToM(int d,int m,char *mnum)//d为十进制数,m为要转换的目标进制数,mnum指向的数组存放转换结果
{int len=0,r=0;//存放mnum指向数组的下标以及余数 do{//除M取余 r=d%m;if(r >= 10) //针对要转换为16进制的情况 mnum[len++] = r - 10 + 'A';   //将对应的整数转换成字母字符else      mnum[len++] = r + '0';     //将对应的整数转换成数字字符d/=m;}while(d!=0);mnum[len]='\0';char t;for(int i=0,j=len-1;i<j;i++,j--)//逆置输出 {t=mnum[i];mnum[i]=mnum[j];mnum[j]=t;}
}

测试输出:


情景三、二进制和八进制、十六进制的转换(总结:通常二进制的3位分别用八进制的3位和十六进制的4位来表示)

首先可以使用上面的方法

  • 将二进制转换为十进制(对应上文讲到的情景一),然后十进制转换为对应的的八进制和十六进制(对应上文讲到的情景二)
  • 亦或者将八进制和十六进制转换为十进制(情景一),然后十进制转化为二进制(情景二)

C语言实现代码(将情景一和情景二的代码整合一下,即借助十进制数作为中介):

/*
N进制到M进制
*/
#include <stdio.h>
#include <string.h>
int NToD(char *a,int base);//将N进制数a转换为十进制数 (N可以考虑二、八、十六进制)
void DToM(int d,int m,char *mnum);//再将十进制转换成M进制(M可以考虑二,八,十六进制)
int getIndexOfSigns(char *ch);//NtoD函数内调用
int main(void)
{int N,M;//要将N进制数转换成M进制数 char Nnum[20],Mnum[20];//存放N进制数以及转换后的M进制数printf("要将N进制数Nnum转换成M进制数请输入以下格式\nN Nnum M:"); scanf("%d %s %d",&N,Nnum,&M);int d=NToD(Nnum,N);//将N进制数Nnum转换成十进制数dDToM(d,M,Mnum);//将十进制数d转换成M进制数Mnumprintf("%d进制数%s转换成%d进制数为:%s\n",N,Nnum,M,Mnum); return 0;
}
int NToD(char *a,int base)
{int sum=0;//变量sum存放a对应的十进制数 int len=strlen(a);//位数 int weight=1;//位权值for(int i=len-1;i>=0;i--)//将N进制从低位向高位输出, 即数组a下标最大的元素为八进制的最低位 {sum+=(getIndexOfSigns(a[i]))*weight;//数组下标i越小,即八进制位数越高,位权weight越重 ,a[i]-'0'将字母映射为十进制数 weight*=base; } return sum;
}
void DToM(int d,int m,char *mnum)
{int len=0,r=0;//存放mnum指向数组的下标以及余数 do{//除M取余 r=d%m;if(r >= 10) //针对要转换为16进制的情况 mnum[len++] = r - 10 + 'A';   //将对应的整数转换成字母字符else      mnum[len++] = r + '0';     //将对应的整数转换成数字字符d/=m;}while(d!=0);mnum[len]='\0';char t;for(int i=0,j=len-1;i<j;i++,j--)//逆置输出 {t=mnum[i];mnum[i]=mnum[j];mnum[j]=t;}
}
int getIndexOfSigns(char *ch)
{if(ch >= '0' && ch <= '9'){return ch - '0';}if(ch >= 'A' && ch <='F') {return ch - 'A' + 10;}if(ch >= 'a' && ch <= 'f'){return ch - 'a' + 10;}return -1;
}

情况三代码是对情况一和情况二的综合,将情况一的int OcToDec()改了一下见名知意的名字int NToD(),内部代码块没改,然后直接使用情况二的void DToM(),然后多加了一个int getIndexOfSigns(char *ch)增加了情况一对16进制的支持。

测试输出结果(其中对情况一中的函数进行了改进,支持16进制转换为10进制):

这里采用一种简便的办法:

二进制整数和八进制整数之间的转换

二进制整数转换为八进制整数时,每三位二进制数字转换为一位八进制数字(由于3位的二进制数最大只能是7,而八进制的数码正是0~7,3位二进制位按权相加得到一个十进制数),运算的顺序是从低位向高位依次进行,高位不足三位用零补齐,最后拼接起来。

二进制整数 1110111100 转换为八进制的结果为 1674:


结果为 1674(八进制)

八进制整数转换为二进制整数时,思路是相反的,每一位八进制数字转换为三位二进制数字,运算的顺序也是从低位向高位依次进行。下图演示了如何将八进制整数 2743 转换为二进制:

结果为010111100011(二进制)

二进制整数和十六进制整数之间的转换

二进制整数转换为十六进制整数时,每四位二进制数字转换为一位十六进制数字,运算的顺序是从低位向高位依次进行,高位不足四位用零补齐。下图演示了如何将二进制整数 10 1101 0101 1100 转换为十六进制:

二进制整数 10 1101 0101 1100 转换为十六进制的结果为 2D5C(注意:十进制数要按十六进制数对应的表示法表示)。

十六进制整数转换为二进制整数时,思路是相反的,每一位十六进制数字转换为四位二进制数字,运算的顺序也是从低位向高位依次进行。下图演示了如何将十六进制整数 A5D6 转换为二进制:


从图中可以看出,十六进制整数 A5D6 转换为二进制的结果为 1010 0101 1101 0110。

C语言笔记:数制与进制(数制)之间转换问题相关推荐

  1. 进制数制系统之间的转换

    目录 一.计算机的数制 1.数制 2.数位→从右开始数的第一个数为第0位 3.基数→几进制数,基数就是几 4.位权→每一位数值*(基数)^数位 二.进制数制系统 1.十进制(满十进一) 2.二进制(满 ...

  2. C语言初阶——6.进制

    C语言初阶--6.进制 1. 进制 百度百科: 进制也就是进位计数制,是人为定义的带进位的计数方法,对于任何一种进制-X进制,就表示每一位置上的数运算时都是逢X进一位. 十进制是逢十进一,十六进制是逢 ...

  3. c语言 乱码转化为16进制_C语言版的16进制与字符串互转函数

    http://www.cnblogs.com/nio-nio/p/3309367.html /* // C prototype : void StrToHex(BYTE *pbDest, BYTE * ...

  4. C语言实现任意进制数之间的转换

    使用C语言编程实现任意进制数(2-16进制)转换为其他任意进制数(2-16进制),实验平台:vs2015. #include<stdio.h> #include<string.h&g ...

  5. c语言怎么减去一个16进制数,一个简单的有关问题:像这样的16进制数怎么转换得到...

    一个简单的问题:像这样的16进制数如何转换得到? 本帖最后由 alibaren 于 2014-11-25 01:15:15 编辑 下列3个整数(用16进制表示) 如何通过某种运算一次性得到右边的数: ...

  6. 进制转换器c语言课程设计作业,C语言课程设计报告--进制转换.doc

    C 语 言 课 程 设 计 报 告 设计题目:学生姓名:学生学号:专业班级:学院名称:同组人姓名:指导老师: 2011年 月 日 1 需求分析 问题描述 输入数据要求 以命令行方式运行程序时所带参数用 ...

  7. [数制与码制]: 有关十进制转换和二进制负数小数补码表示

    文章目录 关于十进制转换 关于二进制负小数补码表示 关于十进制转换 数电第一课,关于各进制数的转换:2,8,16进制的转换也不用说什么,主要是关于10进制转换其他进制会麻烦一点: 而在这之间,由其他进 ...

  8. C++算法进制间的转换

    进制间的转换 进制转换方法是什么? 进制转换的方法是:二进制数,十六进制数可以采用按权展开法转化为十进制数,十进制转化为R进制要分为两部分,其中整数部分要除R取余,直到商为0,小数部分要乘R取余直到得 ...

  9. 计算机不同进制数之间的转换,计算机进制数之间的转换002

    不错 除以16取余和倍数 如: (120)10 120/16 =8 ...8(余8) 8(余数8)/16=0 (8) (120)10 =(88)16 回答人的补充 2009-08-14 09:42 计 ...

最新文章

  1. 【 Notes 】RSSI,LOS versus NLOS,Positioning, Mobility, and Tracking,Network Localization
  2. 推荐“公主妄想症系列之二:第一次”
  3. php.ini 安全配置
  4. 面向对象设计之CRC卡片
  5. opencv光流例程_OpenCV 4.4 发布!新增YOLOv4 和 EfficientDet 推断支持
  6. ARM Cortex-M0(1)---浅谈ARM Cortex-M0
  7. 数据挖掘学习笔记 5 线性回归知识及预测糖尿病实例
  8. flask与js交互的示例代码_QT5.12 C++与前端JavaScript/HTML实现通信交互
  9. ElementUI腾讯云开发者开发指南
  10. 51单片机学习笔记(清翔版)(23)——红外通讯
  11. 51单片机3-红外通信
  12. 欢迎来到Wagtail的文档
  13. 台式电脑自带照片编辑软件将二寸照片改为一寸照片
  14. 开源公告|腾讯代码安全指南开源,涉及C/C++、Go等六门编程语言
  15. 通过身份证号码得到性别和出生日期
  16. 神奇的 ViewDragHelper,让你轻松定制拥有拖拽能力的 ViewGroup
  17. html语言怎么在虚线中加字,html – 用CSS添加虚线spacer / infill
  18. 转行做数据分析的心路历程
  19. 在上海,有哪些牛逼的互联网公司?
  20. 设置字段默认值Java_小书MybatisPlus第9篇-常用字段默认值自动填充

热门文章

  1. 东软载波8Bit MCU开发环境搭建
  2. 焊接机器人焊缝识别焊接机器人计算
  3. 基于BH1750FVI光照传感模块的入射…
  4. hdu_5151_Sit sit sit(区间DP)
  5. 一面阿里,三面字节的后端面试经验分享
  6. 计算机培训专业中心架,武汉模具数控技术专修
  7. tinymce富文本编辑器做评论区
  8. 乌海市六中2021高考成绩查询,2021年贵州高考成绩查询入口【官方】
  9. 微信公众号H5页面获取用户昵称头像等信息(Java)
  10. 济南的老城门(附图)