精华内容
下载资源
问答
  • 虽然很早就接触了二进制,却一直没有正视这个问题,阅读《计算机科学导论》的时候,基本上是跳过了这一部分,总是以“这么基础的东西,反正工作中基本用不上”的理由给搪塞过去。最近正在阅读《编码》和《程序员的...

    虽然很早就接触了二进制,却一直没有正视这个问题,阅读《计算机科学导论》的时候,基本上是跳过了这一部分,总是以“这么基础的东西,反正工作中基本用不上”的理由给搪塞过去。最近正在阅读《编码》和《程序员的数学思维修炼》,心想终究还是得面对的,于是记录了一点笔记,希望不再回避letcode上关于二进制计算的题目。

    10对于我们来讲是一个很平常但又十分神奇的数字。根据《编码》上面的解释,人类的双手非常适合数数,因而我们早已经适应了以10为基础的数字系统。也正是这个习惯,让我在刚接触二进制的时候,感到无比困惑,明明十分简单的概念,却始终不得要领。

    十进制中以0-9这十个数码进行组合来表示数字,且赋予10的整数次幂重大的意义:十,百,千,万,亿...

    那么,什么是二进制呢?

    1. 概念

    二进制就是使用0和1这两个数码进行组合来表示数字的一种计数方法。

    计算机使用二进制的主要优点有:

    技术实现简单,计算机的逻辑电路只需要表示两个状态(电路的断开与连接),使用1和0表示就够了;如果使用十进制,则只能依靠电压的高低进行区分,这无疑会大大增加技术实现的难度

    运算规则简单,二进制的运算规则比十进制少了很多(不需要在文具盒上背诵加法表乘法表了),规则少意味着能够简化计算机的内容结构

    适合逻辑运算,计算机不仅需要进行算术运算,还需要进行逻辑元素,二进制只有两个数码,恰好与逻辑代数中的真和假完全吻合!

    2. 算术运算

    2.1. 四则预算

    2.1.1. 加

    逢二进一

    跟十进制的加法一样,只是进位从10变成了2,这是第一个需要认清的问题

    // 加法表

    0 + 0 = 0;

    1 + 0 = 0;

    0 + 1 = 1;

    1 + 1 = 1; // 进位1

    比如计算111 + 101,从右往左利用基本规则进行计算

    第一位(从右往左的顺序)1 + 1 = 0;,进位1,

    第二位原本是1 + 0,由于进位变成了1 + 1 = 0,继续进位1,

    第三位原本是1 + 1 = 0并进位1,由于进位继续计算0 + 1 = 1,未再次进位

    最后结果1100

    好吧,我放弃用语言描述这个过程了,老老实实拿笔在纸上算两次就好了,实际上跟十进制没有任何区别,只是需要背诵的加法表缩短为仅仅四条了(考虑到加法交换率,实际上只有3条)!

    2.1.2. 减

    借一当二

    // 减法表

    0 - 0 = 0;

    1 - 1 = 0;

    1 - 0 = 1;

    0 - 1 = 1; // 借位为1

    比如计算111 - 101,最后结果10

    2.1.3. 乘

    与十进制相比(九九八十一种),二进制的乘法要简单得多(只有四种),只有1 * 1 = 1,其余全为0

    // 乘法表

    0 * 0 = 0;

    0 * 1 = 0;

    1 * 0 = 0;

    1 * 1 = 1;

    运算过程也与十进制类似,用第二个乘数的每位依次乘以第一个乘数,最后运用加法规则将结果相加,就得到了两个二进制数的乘积,可以理解为:“0乘以任何数都等于0,而1乘以任意数都等于乘数本身”。

    乘法实际上可以看作是加法与移位的操作,如111 * 101可转换为111 + 0000 + 11100 = 100011。

    2.1.4. 除

    // 除法表

    0 / 0 = 0; // 无意义

    1 / 0 = 0; // 无意义

    0 / 1 = 0;

    1 / 1 = 1;

    除法可以使用试商法进行,先从被除数的最高位开始,将被除数(或中间余数)与除数相比较,若被除数(或中间余数)大于除数,则用被除数(或中间余数)减去除数,商为1,并得相减之后的中间余数,否则商为0。再将被除数的下一位移下补充到中间余数的末位,重复以上过程,就可得到所要求的各位商数和最终的余数。

    除法实际上可以看作减法和移位的操作。如:111/101 = 1 余 10。

    2.2. 与十进制的转换

    2.3. 二进制转十进制

    虽然只有0和1两个数码,但是在位置化数字系统中,数码所处的位置不同(位置被称为权),其代表的实际数据大小也不相同。如1101,在二进制中:

    第一个1表示1的个数

    第二个0表示2的个数

    第三个1表示4的个数

    第四个1表示8的个数

    好吧,实际上这儿又被带进坑了。更准确的说法是2的0次幂,2的1次幂,2的2次幂,2的3次幂的个数,只是2的2次幂用十进制表示是4,2的3次方幂用十进制表示是8罢了。

    可见,只需要计算1*1 + 2*0 + 4*1 + 8*1,就可以二进制转换成十进制的数字了,结果显而易见13。其他二进制转十进制同理。

    实际上这种转换方式并不是二进制独有的,其他进制转10进制也可以采用同样的方法,只需要将基数2转换成对应进制的基数就行了。

    2.4. 十进制转二进制

    十进制转二进制看起来要麻烦一点,通常采用“除2取余,逆序排序的方法”。比如将数字23转换为二进制表示的过程可如下表示:

    23/2 = 11...1

    11/2 = 5...1

    5/2 = 2...1

    2/2 = 1...0

    最后结果逆序排序表示为1,0,1,1,1,所以23的二进制表示为10111;

    上述过程用代码展示应该要清晰一些

    function ten2bin(n){

    if (n == 0){

    return 0;

    }

    var res = "";

    while(n){

    res = n%2 + res;

    n = Math.floor(n/2);

    }

    return res;

    }

    3. 逻辑运算

    计算机不仅执行算术运算,也可以执行逻辑运算。在逻辑代数中,只有真和假两种逻辑值,这跟二进制中的仅有的两个数码1和0完全吻合。下面整理了关于逻辑运算的一些东西

    3.1. 基本逻辑运算

    逻辑运算中,"与"、"或"、"非"是三种最基本的运算规则。

    3.1.1. 与

    使用&&表示与运算,参与运算的所有逻辑代数必须全部为真,整个结果才为真。

    在电路中表示就是:所有串联的开关必须全部闭合,灯泡才会通电。

    1&& 1 = 1

    1&& 0 = 0

    0&& 1 = 0

    0&& 0 = 0

    发现没,"与"规则表跟二进制算术运算中的乘法是一模一样的哦!

    3.1.2. 或

    使用||表示或运算,参与运算的所有逻辑代数只要有一个为真,整个结果就为真。

    在电路中表示就是:所有并联的开关只要有一个闭合,灯泡就会通电。

    1|| 0 = 1

    1|| 1 = 1

    0|| 1 = 1

    0|| 0 = 0

    同样地,"或"运算规则表跟二进制算术运算中的加法基本一样(逻辑运算中不存在进位的说法)。

    3.1.3. 非

    使用!表示非运算,整个逻辑表达式的结果与逻辑代数相反

    在电路中表示就是:如果开关闭合,则灯泡被短路;开关断开,灯泡通电

    !1 = 0

    !0 = 1

    3.2. 复杂逻辑运算

    "与"、"或"、"非"是三种最基本的运算规则,其他复杂的逻辑运算都可以用基本运算组合而成。

    与非,运算中所有的逻辑代数都为真,则结果为假,!(a && b && c)

    或非,运算中只要有一个逻辑代数为真,则结果为假,!(a || b || c)

    异或,运算中的两个逻辑代数,有一个为真且另一个为假时,则结果为真,(a&&!b) || (!a && b)

    同或,运算中的两个逻辑代数,都为真或者都为假时,则结果为真,(a && b) || (!a && !b)

    4. 位运算

    大部分高级编程语言都提供了按位操作数字的功能。这一点似乎有些不合理,在日常生活中的计算都是按照某个数字具体代表的值来进行计算的。但是在计算机中,操作数字的某个特定位是很有意义的。下面我们来学习位运算。

    4.1. 位逻辑运算符

    位逻辑运算符与逻辑运算符有很大的区别:

    位逻辑运算符只操作位(位上的数码只可能是0或者1)

    逻辑运算符操作的是真或者假,这是由整个变量的值所决定的

    4.1.1. 位反

    按位取反也叫做二进制反码,使用~表示,指将操作数全部位中的1变成0,将每个0变成1

    ~1011)

    =0100

    按位取反有个小技巧:a取反加一,再取反加一,还等于a 。更通俗一点将,如果操作数为-1,则按位取反结果为0。

    这一点很有用处,很多接口都使用-1来表示程序未返回预期结果,比如JavaScript中的indexOf(),此时可以使用~idx来判断,比起idx === -1要好不少(看起来)。

    4.1.2. 位与

    二进制运算符与&通过对两个操作数逐位进行比较,对于每个位置,只有对应的位都为1时,结果对应位置的值才为1,否则为0

    1010

    & 1100

    = 1000

    位于通常用来实现掩码。

    4.1.3. 位或

    二进制运算符或|通过对两个操作数逐位进行比较,对于每个位置,只要任意一个操作数对应位为1时,结果对应位置的值就为1,否则为0

    1010

    & 1100

    = 1110

    4.1.4. 位异或

    二进制运算符异或^通过对两个操作数逐位进行比较,对于每个位置,只要任意一个操作数对应位为1时,另一个位置为0,结果对应位置的值就为1。

    1010

    ^ 1100

    = 0110

    4.2. 移位运算符

    移位运算符将位向左或向右移动。了解移位运算应当首先了解整数的存储形式,在C语言中,一个int类型的整数占4个字节,而通常一个字节包括8个位,即一个整数包含32位。移位运算就是移动整个操作数在32个位中的位置。

    二进制中的移位运算类似于十进制中的移动小数点的操作,从而快速进行乘除法。

    4.2.1. 左移运算符

    左移运算符<

    1010 << 2

    = 101000

    在不溢出的情况下,左移n位会将操作数扩大2^n倍。

    4.2.2. 右移运算符

    右移运算符将其左侧操作数的值的每位向右移动,并丢弃移出左侧操作数右端的数(肯定会移出的)

    1010 >> 1

    = 101

    5. 八进制与十六进制

    使用二进制存储数据带来的问题是:二进制数字的位数增长十分迅速,保存一个不是很大的数字就需要很长的位数。可见二进制并不适合在计算机外部保存数字,因此产生了八进制和十六进制

    5.1. 八进制

    八进制使用0~7这八个数码来表示数字,由于2^3 = 8,因此二进制和八进制的转换十分方便。

    从二进制转八进制,只需要从右往将三个二进制分为一组(最左不足可用0填充),然后计算为对应的八进制数码,最后将结果拼接在一起就可以了。比如101110:

    将整个数字分为101和110

    101计算结果为2^2 + 1 = 5,110计算结果为2^2 + 2^1 = 6

    所以101110用八进制表示为56

    同理,从八进制转二进制也十分简单,将八进制数字每位拆分成一个三个为二进制数(不足用0填充),然后将结果拼接在一起,比如76用二进制表示为111110,过程这里就不详细写了。

    5.2. 十六进制

    十六进制使用0~9加A~F这十六个数码来表示数字。由于2^4 = 16,加之有了八进制与二进制的相互转换规律,十六进制与二进制的相互转换就轻而易举了,无非是将二进制数按4个一组进行划分,或者将一个十六进制数码转换成4位二进制数

    F2二进制表示为11110010

    101101十六进制表示为2D

    6. 小结

    关于二进制的运算先到这里了,另外还有浮点数等知识,先留个坑了。

    展开全文
  • 二进制数的反码和补码

    千次阅读 2019-01-16 22:12:54
    在大学的学习中,一开始自认为已经学会了反码与补码,但在看到多种表述之后,...首先从最一般的意义上,分别说一下二进制反码和补码: 1、反码 1’s complement 把所有的0变为1,所有的1变为0。 如: 10110010 B...

    在大学的学习中,一开始自认为已经学会了反码与补码,但在看到多种表述之后,反而是越来越乱,疑惑越来越多,即使记住了之后又会混淆,今天又看到了一次,为了防止以后再次忘记,写这篇博客记录一下(记录过程依据《数字电子技术(第十版)》,中英文结合)
    首先从最一般的意义上,分别说一下二进制的反码和补码:

    1、反码 (1’s complement)

    把所有的0变为1,所有的1变为0。
    如:
    10110010 Binary number
    01001101 1’s complement

    2、补码 (2’s complement)

    在反码的最低有效位上加1。
    补码 = 反码 + 1
    另一种求补码的方法:

    1. 从右边的最低有效位开始,往左边写下它们实际的位,直到遇到第一个1(包括1)
    2. 左边剩下的位求反码

    如:
    1011 1000 Binary number
    0100 1000 2’s complement

    这是在不区分正负数的情况下泛泛而谈的,其侧重点在于反码与补码如何操作,但实际上反码和补码的作用是用在带符号数上面的,下面进入重点。

    3、带符号数 Signed Number

    3.1 符号位 The Sign Bit

    带符号的二进制的最左边的那一位就是符号位,指出这个数为正数还是负数,0表示正数,1表示负数。
    下面介绍几种表示带符号数的形式。

    3.2 符号数值的形式 Sign-Magnitude Form

    最左边的一位是符号位,剩余的位都是数值位。其实也就是一般的带符号数的形式,数值位对于正数和负数来说都是二进制源码(in true (uncomplemented) binary)。如十进制数 +25 使用符号数值形式表示成8位带符号二进制数为:
    00011001
    十进制数 -25 表示为:
    在这里插入图片描述
    他们之间的唯一区别就是符号位不同。

    3.3 反码形式 1’s Complement Form

    正数的反码形式:与符号数值形式相同;
    负数的反码形式:相应正数的反码。也就是为相应正数的符号数值形式的每一位取反。

    应当注意的是并不是带符号数的反码都是每一位取反。
    反码和补码其实是为了解决正数和负数的加减法运算的,所以正数其实不用做什么改变,而负数改变形式后可以巧妙解决一些运算问题。比如减去某个数和加上这个数的补码是一样的,这就是为什么计算机在所有的算术运算中都使用补码来表示负整数。
    理解了反码是带符号数的一种表示形式及其目的,大概就能理解为什么正数的反码是其本身,下面要说到的补码也是一样的道理。

    举例:在反码表示形式中,
    十进制数 25 表示为:
    00011001
    十进制数 -25 表示为:
    11100110

    3.4 补码形式 2’s Complement Form

    正数的补码形式:与符号数值形式相同;
    负数的补码形式:负数的反码加1。

    举例:在补码表示形式中,
    十进制数 25 表示为:
    00011001
    十进制数 -25 表示为:
    11100111

    3.5 总结

    对于带符号数,
    正数的反码和补码与原码相同;
    负数的反码等于相应正数的反码,补码等于相应正数的补码。

    但这样的说法是会让人产生疑惑的,因为既然正数的反码等于原码,且负数的反码等于相应正数的反码(即等于正数的原码),那正数负数的表示不就一样了。我也觉得这种说法很有歧义,但如果把第二个反码看成是一种广义上的操作,即把每一位取反,这样就没问题了,总之只要能理解就好,有时候反码就是真的“反”码,实实在在的操作。但为了避免这种困惑,倒不如表述得更清楚直接些:

    对于带符号数,
    正数的反码和补码与原码相同;
    负数的反码等于相应正数的符号数值形式的各个位取反,补码等于反码加1。


    如有不合理的地方,欢迎指正。

    展开全文
  • C语言中8进制和16进制怎么表示 ...所以C语言没有二进制输入,最多可用函数去实现。 八进制数的表达方法 C/C++规定,一个数如果要指明它采用八进制,必须在它前面加上一个0(数字0),如:123是十进制,

    C语言中8进制和16进制怎么表示

    C语言本身支持的三种输入是:
    1. 十进制。比如20,457; 
    2. 十六进制,以0x开头。比如0x7a; 
    3. 八进制,以0开头。比如05,0237

    所以C语言没有二进制输入,最多可用函数去实现。


    八进制数的表达方法

    C/C++规定,一个数如果要指明它采用八进制,必须在它前面加上一个0(数字0),如:123是十进制,但0123则表示采用八进制。这就是八进制数在C、C++中的表达方法。

    C和C++都没有提供二进制数的表达方法

    现在,对于同样一个数,比如是100,我们在代码中可以用平常的10进制表达,例如在变量初始化时:

    int a = 100;

    我们也可以这样写:

    int a = 0144; //0144是八进制的100;


    八进制数在转义符中的使用

    我们学过用一个转义符'/'加上一个特殊字母来表示某个字符的方法,如:'\n'表示换行(line),而'\t'表示Tab字符,'\''则表示单引号。今天我们又学习了另一种使用转义符的方法:转义符'\'后面接一个八进制数,用于表示ASCII码等于该值的字符。

    比如,查一下ASCII码表,我们找到问号字符(?)的ASCII值是63,那么我们可以把它转换为八进值:77,然后用 '\77'来表示'?'。由于是八进制,所以本应写成 '\077',但因为C/C++规定不允许使用斜杠加10进制数来表示字符,所以这里的0可以不写。

    例如:

    printf("\077\n\77\n")

    则输出结果为:

    ?

    ?

    16进制的表示:以0X或0x开头的数字序列(数字0)

    如24就是0x018

    另外,A=10,B=11,C=12,D=13,E=14,F=15

    例如

    #include <stdio.h>
    main()
    {
    int a=0x018,b=24,c=016;
    printf("%d\n",a);
    printf("%d\n",b);
    printf("%d\n",c);
    }

    结果为

    24

    24

    14

    原码,反码及补码

    概述
      在计算机内,有符号数有3种表示法:原码、反码和补码。

      在计算机中,数据是以补码的形式存储的,所以补码在c语言的教学中有比较重要的地位,而讲解补码必须涉及到原码、反码。

    详细释义
    所谓原码就是二进制定点表示法,即最高位为符号位,“0”表示正,“1”表示负,其余位表示数值的大小。   

    反码表示法规定:正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外。   

    补码表示法规定:正数的补码与其原码相同;负数的补码是在其反码的末位加1。

    原码、反码和补码的表示方法

    定点整数表示方法
    原码
    在数值前直接加一符号位的表示法。  

    例如: 符号位 数值位  

    [+7]原= 0 0000111 B   

    [-7]原= 1 0000111 B   

    注意:

    a. 数0的原码有两种形式:

    [+0]原= 00000000B

    [-0]原= 10000000B   

    b. 8位二进制原码的表示范围:-127~+127


    定点小数表示方法

    反码
    正数:正数的反码与原码相同。

    负数:负数的反码,符号位为“1”,数值部分按位取反。

    例如: 符号位 数值位

    [+7]反= 0 0000111 B

    [-7]反= 1 1111000 B

    注意:

    a. 数0的反码也有两种形式,即

    [+0]反=00000000B

    [- 0]反=11111111B

    b. 8位二进制反码的表示范围:-127~+127

    补码
    1)模的概念:把一个计量单位称之为模或模数。

    例如,时钟是以12进制进行计数循环的,即以12为模。在时钟上,时针加上(正拨)12的整数位或减去(反拨)12的整数位,时针的位置不变。

    对于一个模数为12的循环系统来说,加2和减10的效果是一样的;因此,在以12为模的系统中,凡是减10的运算都可以用加2来代替,这就把减法问题转化成加法问题了(注:计算机的硬件结构中只有加法器,所以大部分的运算都必须最终转换为加法)。

    10和2对模12而言互为补数。   

    同理,计算机的运算部件与寄存器都有一定字长的限制(假设字长为8),因此它的运算也是一种模运算。当计数器计满8位也就是256个数后会产生溢出,又从头开始计数。产生溢出的量就是计数器的模,显然,8位二进制数,它的模数为2^8=256。在计算中,两个互补的数称为“补码”。   

    2)补码的表示:  

    正数:正数的补码和原码相同。

    负数:负数的补码则是符号位为“1”。并且,这个“1”既是符号位,也是数值位。数值部分按位取反后再在末位(最低位)加1。也就是“反码+1”。

    例如: 符号位 数值位

    [+7]补= 0 0000111 B

    [-7]补= 1 1111001 B

    补码在微型机中是一种重要的编码形式,请注意:

    a. 采用补码后,可以方便地将减法运算转化成加法运算,运算过程得到简化。

    正数的补码即是它所表示的数的真值,而负数的补码的数值部份却不是它所表示的数的真值。

    采用补码进行运算,所得结果仍为补码。

    b. 与原码、反码不同,数值0的补码只有一个,即

    [0]补=00000000B。

    若字长为8位,则补码所表示的范围为-128~+127;进行补码运算时,应注意所得结果不应超过补码所能表示数的范围。

    原码、反码和补码之间的转换
    由于正数的原码、补码、反码表示方法均相同,不需转换。

    在此,仅以负数情况分析。
    (1) 已知原码,求补码。
      例:已知某数X的原码为10110100B,试求X的补码和反码

    解:由[X]原=10110100B知,X为负数。求其反码时,符号位不变,数值部分按位求反;求其补码时,再在其反码的末位加1。

    1 0 1 1 0 1 0 0 原码

    1 1 0 0 1 0 1 1 反码,符号位不变,数值位取反

    1 +1

    1 1 0 0 1 1 0 0 补码

    故:[X]补=11001100B,[X]反=11001011B。
    (2) 已知补码,求原码。
    分析:按照求负数补码的逆过程,数值部分应是最低位减1,然后取反。但是对二进制数来说,先减1后取反和先取反后加1得到的结果是一样的,故仍可采用取反加1 有方法。

    例:已知某数X的补码11101110B,试求其原码。

    解:由[X]补=11101110B知,X为负数。

    1 1 1 0 1 1 1 0 补码

    1 1 1 0 1 1 0 1 反码(减1)

    1 0 0 1 0 0 1 0 原码(符号位不变,其它取反)   


     有符号数运算时的溢出问题

    比如在32位机上1的原码是(十六进制) 0000 0001,那么它的反码是
    1111 1110。

    补码也是:1111 1110。
    补码:正数的补码就是其反码(也是其原码), 负数的补码是其原码按位取反,并在末位加一,所以
    1 的补码也是0000 0001
    而-1 的补码 是 1111 1110 再末位加1, 变成 1111 1111
    即32位机器上-1的补码是 1111 1111 1111 1111 1111 1111 1111 1111

    换算成十六进制就是ffff ffff

    见下面的例子:

    #include <stdio.h>
    main()
    {
    int a=1,b=-1;
    printf("%x\n",a);
    printf("%x\n",b);
    printf("%X\n",a);
    printf("%X\n",b);
    }

    结果:

    1
    ffffffff
    1
    FFFFFFFF


    typedef unsigned short int Uint16;
    Uint16 a=10;
    Uint16 b=20;
    那么Uint16 c= a-b得到65526,
    short int d=a-b得到-10,


    C语言按位取反运算符~

    注意:C语言的按位取反运算,对于符号位同样取反

    C语言~12 按位取反的结果 是什么?

    short 型为例 12的二进制为0000 1100

    取反便成了。1111 0011

    而这个数用带符号的整形(%d打印出)表示为-13

    ------------------------

    负数的绝对值等于: 取反 + 1

    1111 0011 取反加1为0000 1101 = 13

    所以为-13

    最高位为符号位

    -----------------------------------

    printf("%x,%d\n",~7,~7);//输出:fffffff8,-8

    源码编译环境vs.net2005、32位机

    //.NETCLR规定整型变量默认为int类型,也就是说此处的7在内存中占有4个字节。

    00000000 00000000 00000000 00000111(7)

    按位取反运算 
    11111111 11111111 11111111 11111000 
    printf("%x\n",~7)//十六进制输出:fffffff8
    printf("%d\n",~7)//十进制输出 :-8

    之所以出现-8在于结果溢出,比如

    printf("%u\n",~7)//十进制输出 :4294967288

    因此,输出结果为-8在于超过了int的范围



    展开全文
  • 比如05,0237所以C语言没有二进制输入,最多可用函数去实现。八进制数的表达方法C/C++规定,一个数如果要指明它采用八进制,必须在它前面加上一个0(数字0),如:123是十进制,但0123则表示采用八进制。这就是八进制数...

    C语言中8进制和16进制怎么表示

    C语言本身支持的三种输入是:

    1. 十进制。比如20,457;

    2. 十六进制,以0x开头。比如0x7a;

    3. 八进制,以0开头。比如05,0237

    所以C语言没有二进制输入,最多可用函数去实现。

    八进制数的表达方法

    C/C++规定,一个数如果要指明它采用八进制,必须在它前面加上一个0(数字0),如:123是十进制,但0123则表示采用八进制。这就是八进制数在C、C++中的表达方法。

    C和C++都没有提供二进制数的表达方法

    现在,对于同样一个数,比如是100,我们在代码中可以用平常的10进制表达,例如在变量初始化时:

    int a = 100;

    我们也可以这样写:

    int a = 0144; //0144是八进制的100;

    千万记住,用八进制表达时,你不能少了最前的那个0。否则计算机会通通当成10进制。不过,有一个地方使用八进制数时,却可以不使用加0,那就是用于表达字符的“转义符”表达法。

    八进制数在转义符中的使用

    我们学过用一个转义符'/'加上一个特殊字母来表示某个字符的方法,如:'\n'表示换行(line),而'\t'表示Tab字符,'\''则表示单引号。今天我们又学习了另一种使用转义符的方法:转义符'\'后面接一个八进制数,用于表示ASCII码等于该值的字符。

    比如,查一下ASCII码表,我们找到问号字符(?)的ASCII值是63,那么我们可以把它转换为八进值:77,然后用 '\77'来表示'?'。由于是八进制,所以本应写成 '\077',但因为C/C++规定不允许使用斜杠加10进制数来表示字符,所以这里的0可以不写。

    例如:

    printf("\077\n\77\n")

    则输出结果为:

    ?

    ?

    16进制的表示:以0X或0x开头的数字序列(数字0)

    如24就是0x018

    另外,A=10,B=11,C=12,D=13,E=14,F=15

    例如

    #include

    main()

    {

    int a=0x018,b=24,c=016;

    printf("%d\n",a);

    printf("%d\n",b);

    printf("%d\n",c);

    }

    结果为

    24

    24

    14

    原码,反码及补码

    概述  在计算机内,有符号数有3种表示法:原码、反码和补码。

    在计算机中,数据是以补码的形式存储的,所以补码在c语言的教学中有比较重要的地位,而讲解补码必须涉及到原码、反码。

    详细释义所谓原码就是二进制定点表示法,即最高位为符号位,“0”表示正,“1”表示负,其余位表示数值的大小。

    反码表示法规定:正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外。

    补码表示法规定:正数的补码与其原码相同;负数的补码是在其反码的末位加1。

    原码、反码和补码的表示方法

    f9fae7e601d79bafc8c81f2a45e7d6a7.gif

    定点整数表示方法

    原码在数值前直接加一符号位的表示法。

    例如: 符号位 数值位

    [+7]原= 0 0000111 B

    [-7]原= 1 0000111 B

    注意:

    a. 数0的原码有两种形式:

    [+0]原= 00000000B

    [-0]原= 10000000B

    b. 8位二进制原码的表示范围:-127~+127

    f21c197776eef56d8bdd9c20cb56b4d2.gif

    定点小数表示方法

    反码正数:正数的反码与原码相同。

    负数:负数的反码,符号位为“1”,数值部分按位取反。

    例如: 符号位 数值位

    [+7]反= 0 0000111 B

    [-7]反= 1 1111000 B

    注意:

    a. 数0的反码也有两种形式,即

    [+0]反=00000000B

    [- 0]反=11111111B

    b. 8位二进制反码的表示范围:-127~+127

    补码1)模的概念:把一个计量单位称之为模或模数。

    例如,时钟是以12进制进行计数循环的,即以12为模。在时钟上,时针加上(正拨)12的整数位或减去(反拨)12的整数位,时针的位置不变。

    对于一个模数为12的循环系统来说,加2和减10的效果是一样的;因此,在以12为模的系统中,凡是减10的运算都可以用加2来代替,这就把减法问题转化成加法问题了(注:计算机的硬件结构中只有加法器,所以大部分的运算都必须最终转换为加法)。

    10和2对模12而言互为补数。

    同理,计算机的运算部件与寄存器都有一定字长的限制(假设字长为8),因此它的运算也是一种模运算。当计数器计满8位也就是256个数后会产生溢出,又从头开始计数。产生溢出的量就是计数器的模,显然,8位二进制数,它的模数为2^8=256。在计算中,两个互补的数称为“补码”。

    2)补码的表示:

    正数:正数的补码和原码相同。

    负数:负数的补码则是符号位为“1”。并且,这个“1”既是符号位,也是数值位。数值部分按位取反后再在末位(最低位)加1。也就是“反码+1”。

    例如: 符号位 数值位

    [+7]补= 0 0000111 B

    [-7]补= 1 1111001 B

    补码在微型机中是一种重要的编码形式,请注意:

    a. 采用补码后,可以方便地将减法运算转化成加法运算,运算过程得到简化。

    正数的补码即是它所表示的数的真值,而负数的补码的数值部份却不是它所表示的数的真值。

    采用补码进行运算,所得结果仍为补码。

    b. 与原码、反码不同,数值0的补码只有一个,即

    [0]补=00000000B。

    若字长为8位,则补码所表示的范围为-128~+127;进行补码运算时,应注意所得结果不应超过补码所能表示数的范围。

    原码、反码和补码之间的转换由于正数的原码、补码、反码表示方法均相同,不需转换。

    在此,仅以负数情况分析。

    (1) 已知原码,求补码。

    例:已知某数X的原码为10110100B,试求X的补码和反码

    解:由[X]原=10110100B知,X为负数。求其反码时,符号位不变,数值部分按位求反;求其补码时,再在其反码的末位加1。

    1 0 1 1 0 1 0 0 原码

    1 1 0 0 1 0 1 1 反码,符号位不变,数值位取反

    1 +1

    1 1 0 0 1 1 0 0 补码

    故:[X]补=11001100B,[X]反=11001011B。

    (2) 已知补码,求原码。

    分析:按照求负数补码的逆过程,数值部分应是最低位减1,然后取反。但是对二进制数来说,先减1后取反和先取反后加1得到的结果是一样的,故仍可采用取反加1 有方法。

    例:已知某数X的补码11101110B,试求其原码。

    解:由[X]补=11101110B知,X为负数。

    1 1 1 0 1 1 1 0 补码

    1 1 1 0 1 1 0 1 反码(符号位不变,数值位取反加1)

    1 0 0 1 0 0 1 0 原码(符号位不变,数值位取反)   1.3.2 有符号数运算时的溢出问题

    比如在32位机上1的原码是(十六进制) 0000 0001,那么它的反码是

    1111 1110。

    补码也是:1111 1110。

    补码:正数的补码就是其反码(也是其原码), 负数的补码是其原码按位取反,并在末位加一,所以

    1 的补码也是0000 0001

    而-1 的补码 是 1111 1110 再末位加1, 变成 1111 1111

    即32位机器上-1的补码是 1111 1111 1111 1111 1111 1111 1111 1111

    换算成十六进制就是ffff ffff

    见下面的例子:

    #include

    main()

    {

    int a=1,b=-1;

    printf("%x\n",a);

    printf("%x\n",b);

    printf("%X\n",a);

    printf("%X\n",b);

    }

    结果:

    1

    ffffffff

    1

    FFFFFFFF

    C语言按位取反运算符~

    注意:C语言的按位取反运算,对于符号位同样取反:如

    C语言~12 按位取反的结果 是什么?

    short 型为例 12的二进制为0000 1100

    取反便成了。1111 0011

    而这个数用带符号的整形(%d打印出)表示为-13

    ------------------------

    负数的绝对值等于: 取反 + 1

    1111 0011 取反加1为0000 1101 = 13

    所以为-13

    最高位为符号位

    -----------------------------------

    printf("%x,%d\n",~7,~7);//输出:fffffff8,-8

    源码编译环境vs.net2005、32位机

    //.NETCLR规定整型变量默认为int类型,也就是说此处的7在内存中占有4个字节。

    00000000 00000000 00000000 00000111(7)

    按位取反运算

    11111111 11111111 11111111 11111000

    printf("%x\n",~7)//十六进制输出:fffffff8

    printf("%d\n",~7)//十进制输出 :-8

    之所以出现-8在于结果溢出,比如

    printf("%u\n",~7)//十进制输出 :4294967288

    因此,输出结果为-8在于超过了int的范围

    例如:下面两正数相加结果变成了负数.

    1)(+72)+(+98)=?

    0 1 0 0 1 0 0 0 B +72

    + 0 1 1 0 0 0 1 0 B +98

    1 0 1 0 1 0 1 0 B -86

    补码的真值例:-65

    原码:11000001

    反码:10111110

    补码::10111111

    若直接将10111111转换成十进制,发现结果并不是-65,而是191。

    那么,如何得到其真值呢?

    直接按照补码的反过程就行了:

    如果要得到一个负二进制数的真值,只要先减1,然后各位取反(不包括符号位)就行了。

    二进制值:10111111(-65的补码)

    减1 :10111110

    各位取反:11000001

    此变为结果

    ~-2 结果是1

    展开全文
  • 2.对十进制转二进制完全char化,对二进制没有长度限制,只对十进制数有限制,只需要把int类型改成longlong类型就可以进一步扩大。 3.可以自定义输出的位长,为以后的调用做好准备。 #include <stdio.h> #...
  • 补码  计算机是按照补码的形式存数字的。int32位补码形式的最大值2^31-1,最小值-2^31。...二进制小数部分转化为十进制时,权值的为负次幂。 十进制小数部分转化为二进制时,乘2取整。
  • 不能体现补码的取值范围与反码不同的特点。 本代码在code::blocks17.12中正常运行 #include <stdio.h> #include <stdlib.h> #define MAXSIZE 64 typedef struct rational_number{ char charnum[MAXSIZE...
  • 二进制数据的表示方法2.1 有符号数与无符号数2.2 二进制的补码表示法2.3 二进制反码表示法2.4 小数二进制补码表示三.二进制的运算3.1 定点数与浮点数3.1.1 定点数的表示方法3.1.2 浮点数的表示方法3.1.3 定点数...
  • 首先,什么是反码,补码 原码 (1) 原码:在数值前直接加一符号位的表示法。 例如: 符号位 数值位 [+7]原= 0 0000111 B ...注意:a....定点小数表示方法 ...b. 8位二进制原码的表示范围:-12
  • 二进制1.1.原码1.2.反码1.3.补码2.八进制3.十六进制4.位运算4.1.与(&)运算4.2.或(|)运算4.3.非(~)运算4.4.异或(^)运算4.5.移位(<<   >>   >>>)...
  • 二进制 真值 原码 反码 补码

    千次阅读 2017-02-22 14:16:02
    正数的补码与其原码相同 ,负数二进制补码 先求与之对应的正数二进制数 然后所有位取反加1 不够位数时左边加1   例如,[+1]=[0000 0001]原=[0000 0001]反=[0000 0001]补,[-1]=[1000 0001]原=[1111 1110]反=...
  • 原码表示法是机器数的一种简单的表示法。其符号位用0表示正号,用:表示负号,数值一般用二进制形式表示。设有一数为x,则原码表示可记作〔x〕原。 例如,X1= +1010110 ...当用8位二进制来表示小数原码时,
  • 2.1 为了不累赘描述,本文以百度的二进制小数转换为十进制小数为例,如下图 2.2 十进制整数转二进制整数以及十进制小数转换为二进制小数如下 3. 原码、反码和补码 在理解二进制和十进制转换后,对于一个...
  • 1 机器数和真值1.1 机器数一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1.比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制...
  • 二进制原码、反码、补码详解

    万次阅读 多人点赞 2015-05-05 09:51:12
    ① 原码: ... 其中,第一个数字0是符号位,0表示正数,0 000110是数字6的二进制数据表示。  数字-6 在计算机中原码表示为:1 000 0110  以上是在8位计算机中的原码表示,如果在32位或16位计算机中,
  • 二进制,位运算,移位运算 1.二进制 对于原码, 反码, 补码而言, 需要注意以下几点: (1).Java中没有无符号数, 换言之, Java中的数都是有符号的; (2).二进制的最高位是符号位, 0表示正数, 1表示负数; (3).正数的...
  • 原码、反码、补码 数值在计算机中是以补码的方式存储的,在探求为何... 一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1。...
  • 计算机基础:16、二进制--有符号数和无符号数1、有符号数和无符号数1.1、二进制原码表示法1.2、二进制的补码表示法1.3、二进制反码1.4、小数的补码1.5、原码、补码、反码总结 1、有符号数和无符号数 1.1、二进制...
  • 在java中一个byte类型的值占据的存储空间是1个字节,每个字节8位,那么就有8位的空间用来存二进制数,那么该怎么计算byte类型的取值范围呢? 首先,java中的最高位是符号位,0是正数,1是负数。 那么byte的正数...
  • - 整数型(不带小数的数字):byte,short,int,long ,分别占用字节1,2,4,8个字节 - 浮点型(带小数的数字):float,double ,区别是占用内存大小不一样分别是4,8字节 - 布尔型(真和假):boolean 占用1个字节 -...
  • 十进制(小数)转换为二进制(8位): 原码:首位是符号位,其余的n-1位表示数值的绝对值,数位不够用0补足。数值0的原码有两种形式:[+0] 原=00000000, [-0]原=10000000。 正数的原码、反码、补码都一致。 ...
  • 二进制(原码、反码、补码)(转载)

    千次阅读 2017-11-02 15:43:09
    bit(位):数据存储的最小单元...在计算机二进制系统中,位,简记为b,也称为比特(bit),每个二进制数字0或1就是一个位(bit),其中每 8bit = 1 byte(字节); Java 中的int数据类型占4个byte(字节),而1 byte(字节) =
  • 二进制的运算 首先讲到的是十进制转化为二进制,因为以人类的思维观是十进制的。生活中,十进制的计数值早已经习惯了我们的生活,但在计算机领域,十进制是行不通的,在早期的晶体管中,只有高低电平两种状态之分。...
  • 各种进制之间的相互转换...二进制 逢二进一 八进制 逢八进一 十六进制 逢十六进一 十进制—>二/八/十六进制 口诀 整数部分,除2/8/16取余; 小数部分,乘2/8/16取整 例:23.25转换成二进制为10111.01 二...
  • 1.常用的数制十进制 0~9八进制 0~7二进制 0~1十六进制 0~F2.十进制 转 各个进制方法 : 除以基数取余反向3. 2进制 8进制 16进制 转十进制二进制___________________________2^3 2^2 2^1 2^01 0 0 1 X=8+ 1 = 9八进制...
  • 是8位的二进制数据,前1位是符号位,后7位是数据真值(int类型的32位实在是太多了,就拿byte类型来举例子),首先说明一个概念,计算机是使用二进制的补码来存储汇编的机器码,这里边有三个知识点:原码、反码、补码...
  • 对于初学者,迟早要面对进制的转换,或许

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,032
精华内容 2,812
关键字:

二进制小数的反码