C语言基础——进制转换

程序中进制的表示

二进制

二进制由 0 和 1 两个数字组成,使用时必须以0b或0B(不区分大小写)开头,例如:

//合法二进制

int a = 0b101; //换算成十进制5

int b = -0b110010; //换算成十进制-50

int c = 0B100001; //换算成十进制33

//不合法的二进制

int m = 101001; //无前缀0b或0B,相当于十进制

int n = 0B401; //4不是有效的二进制数字

请注意,标准的C语言并不支持上面的二进制写法,只是有些编译器自己进行了扩展,才支持二进制数字。换句话说,并不是所有的编译器都支持二进制数字,只有一部分编译器支持,并且跟编译器的版本有关系。

下面是实际测试的结果:

  • Visual C++ 6.0 不支持。
  • Visual Studio 2015 支持,但是 Visual Studio 2010 不支持;可以认为,高版本的 Visual Studio 支持二进制数字,低版本的 Visual Studio 不支持。
  • GCC 4.8.2 支持,但是 GCC 3.4.5 不支持;可以认为,高版本的 GCC 支持二进制数字,低版本的 GCC 不支持。
  • LLVM/Clang 支持(内嵌于 Mac OS 下的 Xcode 中)。
  • window VScode支持

运算法则:逢二进一,借一当二

0B1101 - 0B0011 = 0B1010

0B1101 + 0B0011 = 0B10000

八进制

八进制由 0~7 八个数字组成,使用时必须以0开头(注意是数字 0,不是字母 o),例如:

//合法八进制 int a = 0105;

//换算成十进制69 0105 105

int b = -0101; //换算成十进制-65

int c = 017777; //换算成十进制8191

//不合法的八进制

int m = 256; //无前缀0,相当于十进制

int n = 0810; //8不是有效的八进制数字

运算法则:逢八进一,借一当八

0720 - 0101 = 0617

0325 + 0316 = 0643

十六进制

十六进制由数字 0~9、字母 A~F 或 a~f( 不区分大小写 A == 10 B==11 C==12 D==13 E==14 F==15)组成,使用时必须以0x或0X(不区分大小写)开头,例如:

//合法十六进制

int a = 0x2B; //换算成十进制43

int b = -0xA0; //换算成十进制160

int c = 0X70; //换算成十进制112

//不合法的十六进制

int m = 5A; //无前缀0X,是一个无效的数字

int n = 0x6H; //H一个无效的十六进制数字

运算法则:逢十六进一,借一当十六

0x71 - 0x2C = 0x45

0x88 + 0xA8 = 0x130

十进制

十进制由 0~9 十个数字组成,没有任何前缀,和我们平时的书写格式一样,不再赘述。

98 521 44

进制之间的转换

十进制转二进制(八进制、十六进制)

方法为:十进制数除2取余法。(转八进制时为除8取余法;转十六进制时除16取余),一直除,除到商为0时,反着取余数

例如:把十进制数 150 转换为 二进制数:如下:10010110

100化成二进制:

110 0100

权位值

2 进制

8192 4096 2048 1024 512 256 128 64 32 16 8 4 2 1

独特转化方法:将数字进行拆解,必须按最近最大权位值拆解,将有数字的位进行置即可。

100 = 64 + 32 + 4

64 32 16 8 4 2 1

1 1 0 0 1 0 0

819 = 512 + 256 + 32 + 16 + 2 + 1 转化二进制:1 1 0 0 1 1 0 0 1 1

二进制转十进制、八进制转十进制、十六进制转十进制

向十进制转时,将各位数按权展开,从右向左依次拿每位上的数乘以二(八 / 十六)的 0 1 2 ……次方,然后相加的和即是相应的十进制数。

权位值

2048 1024 512 256 128 64 32 16 8 4 2 1

独特转化方法:将对应的二进制权位值进行相加即可得对应的十进制数

1 1 0 1 0 1 化成十进制:32+16+4+1 = 53

32 16 8 4 2 1 (权位值)

1 1 0 1 0 1

二进制转八进制

方法为:每3位二进制数按权合成,然后相加得到1位八进制数。(注意事项,每3位二进制转成八进制是从右到左开始转换,不足时补0)。

001 101 001 011 010

010 = 2^1

011 = 2^1+2^0

第一步骤先分组:001 101 001 011 010

第二步,按权值合成八进制:0 15132

八进制转二进制

方法为:将八进制数的每一位通过除2取余法得到一个二进制数(也可以通过权值法),这个二进制数必须是3位,如果不够3 位,则最左补0。

值为:0226

0712 =0B111001010

0556=0B101101110

二进制转十六进制

与二进制转八进制相似,每四位按权相加得到一个数,从最右开始,最后若不足4位则向最左边补0,然后得到十六进制数。

0B1011011011110

步骤一:先分组(4位为一组): 0001 0110 1101 1110 = 0x1 6 D E

十六进制转二进制

方法为:将十六进制数的每一位通过除2取余法(也可以通过权值法),得到二进制数,每一位十六进制数得到的二进制数都应该是4位,不足时在最左边补零。

0xDD8 = 0B 1101 1101 1000

十六进制转八进制(八进制转十六进制)

方法为:借用一个中间进制,即先将十六进制(八进制)转换为二进制,然后再将二进制转换为八进制(十六进制)

0xA9F = 1010 1001 1111 (二进制) = 101 010 011 111 (二进制) = 0 5 2 3 7

                                分(二进制)                                 合(八进制)

0xE139A = 0B1110 0001 0011 1001 1010 = 011 100 001 001 110 011 010 = 03411632

进制之前转化总结

(1)记住二进制与十进制权位值关系

512 256 128 64 32 16 8 4 2 1

  1     1     1    1   1   1  1 1 1 1

(2)进制之间转化要借助中间进制

十六进制转八进制借二进制, 十进制转八进制借用二进制,十六进制转十进制借二进制。

二进制数、八进制数和十六进制数的输出

C语言中常用的整数有 short、int 和 long 三种类型,通过 printf 函数,可以将它们以八进制、十进制和十六进制的形式输出。下表列出了不同类型的整数、以不同进制的形式输出时对应的格式控制符:

十六进制数字的表示用到了英文字母,有大小写之分,要在格式控制符中体现出来:

  • %hx、%x 和 %lx 中的x小写,表明以小写字母的形式输出十六进制数;
  • %hX、%X 和 %lX 中的X大写,表明以大写字母的形式输出十六进制数。

注意:八进制数字和十进制数字不区分大小写,所以格式控制符都用小写形式。如果你比较叛逆,想使用大写形式,那么行为是未定义的,请你慎重:

  • 有些编译器支持大写形式,只不过行为和小写形式一样;
  • 有些编译器不支持大写形式,可能会报错,也可能会导致奇怪的输出。

注意:虽然部分编译器支持二进制数字的表示,但是却不能使用 printf 函数输出二进制,这一点比较遗憾。当然,通过转换函数可以将其它进制数字转换成二进制数字,并以字符串的形式存储,然后在 printf 函数中使用%s输出即可

eg:

#include <stdio.h>

int main()

{    

 short a = 0b1010110;  //二进制数字     

int b = 02713;  //八进制数字     

long c = 0X1DAB83;  //十六进制数字         

    printf("a=%ho, b=%o, c=%lo\n", a, b, c);  //以八进制形似输出     printf("a=%hd, b=%d, c=%ld\n", a, b, c);  //以十进制形式输出     printf("a=%hx, b=%x, c=%lx\n", a, b, c);  //以十六进制形式输出(字母小写)     printf("a=%hX, b=%X, c=%lX\n", a, b, c);  //以十六进制形式输出(字母大写)    

 return 0;

}

输出时加上前缀

区分不同进制数字的一个简单办法就是,在输出时带上特定的前缀。在格式控制符中加上#即可输出前缀,例如 %#x、%#o、%#lX、%#ho 等。

十进制数字没有前缀,所以不用加#。如果你加上了,那么它的行为是未定义的,有的编译器支持十进制加#,只不过输出结果和没有加#一样,有的编译器不支持加#,可能会报错,也可能会导致奇怪的输出;但是,大部分编译器都能正常输出,不至于当成一种错误。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值