无符号型和有符号数

无符号型和有符号数
无符号型和有符号数

理解有符号数和无符号数

2008-09-23 14:15

负数在计算机中如何表示呢?

这一点,你可能听过两种不同的回答。

一种是教科书,它会告诉你:计算机用“补码”表示负数。可是有关“补码”的概念一说就得一节课,这一些我们需要在第6章中用一章的篇幅讲2进制的一切。再者,用“补码”表示负数,其实一种公式,公式的作用在于告诉你,想得问题的答案,应该如何计算。却并没有告诉你为什么用这个公式就可以和答案?

另一种是一些程序员告诉你的:用二进制数的最高位表示符号,最高位是0,表示正数,最高位是1,表示负数。这种说法本身没错,可是如果没有下文,那么它就是错的。至少它不能解释,为什么字符类型的-1用二进制表示是“1111 1111”(16进制为FF);而不是我们更能理解的“1000 0001”。(为什么说后者更好理解呢?因为既然说最高位是1时表示负数,那1000 0001不是正好是-1吗?)。

让我们从头说起。

1、你自已决定是否需要有正负。

就像我们必须决定某个量使用整数还是实数,使用多大的范围数一样,我们必须自已决定某个量是否需要正负。如果这个量不会有负值,那么我们可以定它为带正负的类型。

在计算机中,可以区分正负的类型,称为有符类型,无正负的类型(只有正值),称为无符类型。

数值类型分为整型或实型,其中整型又分为无符类型或有符类型,而实型则只有符类型。

字符类型也分为有符和无符类型。

比如有两个量,年龄和库存,我们可以定前者为无符的字符类型,后者定为有符的整数类型。

2、使用二制数中的最高位表示正负。

首先得知道最高位是哪一位?1个字节的类型,如字符类型,最高位是第7位,2个字节的数,最高位是第15位,4个字节的数,最高位是第31位。不同长度的数值类型,其最高位也就不同,但总是最左边的那位(如下示意)。字符类型固定是1个字节,所以最高位总是第7位。

(红色为最高位)

单字节数:1111 1111

双字节数:1111 1111 1111 1111

四字节数:1111 1111 1111 1111 1111 1111 1111 1111

当我们指定一个数量是无符号类型时,那么其最高位的1或0,和其它位一样,用来表示该数的大小。

当我们指定一个数量是无符号类型时,此时,最高数称为“符号位”。为1时,表示该数为负值,为0时表示为正值。

3、无符号数和有符号数的范围区别。

无符号数中,所有的位都用于直接表示该值的大小。有符号数中最高位用于表示正负,所以,当为正值时,该数的最大值就会变小。我们举一个字节的数值对比:

无符号数: 1111 1111 值:255 1* 27 + 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20

有符号数: 0111 1111 值:127 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20

同样是一个字节,无符号数的最大值是255,而有符号数的最大值是127。原因是有符号数中的最高位被挪去表示符号了。并且,我们知道,最高位的权值也是最高的(对于1字节数来说是2的7次方=128),所以仅仅少于一位,最大值一下子减半。

不过,有符号数的长处是它可以表示负数。因此,虽然它的在最大值缩水了,却在负值的方向出现了伸展。我们仍一个字节的数值对比:

无符号数: 0 ----------------- 255

有符号数: -128 --------- 0 ---------- 127

同样是一个字节,无符号的最小值是 0 ,而有符号数的最小值是-128。所以二

者能表达的不同的数值的个数都一样是256个。只不过前者表达的是0到255

这256个数,后者表达的是-128到+127这256个数。

一个有符号的数据类型的最小值是如何计算出来的呢?

有符号的数据类型的最大值的计算方法完全和无符号一样,只不过它少了一个最高位(见第3点)。但在负值范围内,数值的计算方法不能直接使用1* 26+ 1* 25的公式进行转换。在计算机中,负数除为最高位为1以外,还采用补码形式进行表达。所以在计算其值前,需要对补码进行还原。这些内容我们将在第六章中的二进制知识中统一学习。

这里,先直观地看一眼补码的形式:

以我们原有的数学经验,在10进制中:1 表示正1,而加上负号:-1 表示和1相对的负值。

那么,我们会很容易认为在2进制中(1个字节): 0000 0001 表示正1,则高位为1后:1000 0001应该表示-1。

然而,事实上计算机中的规定有些相反,请看下表:

首先我们看到,从-1到-128,其二进制的最高位都是1(表中标为红色),正如我们前面的学。

然后我们有些奇怪地发现,1000 0000 并没有拿来表示 -0;而1000 0001也不是拿来直观地表示-1。事实上,-1 用1111 1111来表示。

怎么理解这个问题呢?先得问一句是-1大还是-128大?

当然是 -1 大。-1是最大的负整数。以此对应,计算机中无论是字符类型,或者是整数类型,也无论这个整数是几个字节。它都用全1来表示 -1。比如一个字节的数值中:1111 1111表示-1,那么,1111 1111 - 1 是什么呢?和现实中

的计算结果完全一致。1111 1111 - 1 = 1111 1110,而1111 1110就是-2。这样一直减下去,当减到只剩最高位用于表示符号的1以外,其它低位全为0时,就是最小的负值了,在一字节中,最小的负值是1000 0000,也就是-128。

我们以-1为例,来看看不同字节数的整数中,如何表达-1这个数:

可能有同学这时会混了:为什么 1111 1111 有时表示255,有时又表示-1?所以我再强调一下本节前面所说的第2点:你自已决定一个数是有符号还是无符号的。写程序时,指定一个量是有符号的,那么当这个量的二进制各位上都是1时,它表示的数就是-1;相反,如果事选声明这个量是无符号的,此时它表示的就是该量允许的最大值,对于一个字节的数来说,最大值就是255。

原码、反码、补码

我们已经知道计算机中,所有数据最终都是使用二进制数表达。

我们也已经学会如何将一个10进制数如何转换为二进制数。

不过,我们仍然没有学习一个负数如何用二进制表达。

比如,假设有一 int 类型的数,值为5,那么,我们知道它在计算机中表示为:00000000 00000000 00000000 00000101

5转换成二制是101,不过int类型的数占用4字节(32位),所以前面填了一堆0。

现在想知道,-5在计算机中如何表示?

在计算机中,负数以其正值的补码形式表达。

什么叫补码呢?这得从原码,反码说起。

原码:一个整数,按照绝对值大小转换成的二进制数,称为原码。

比如 00000000 00000000 00000000 00000101 是 5的原码。

反码:将二进制数按位取反,所得的新二进制数称为原二进制数的反码。

取反操作指:原为1,得0;原为0,得1。(1变0; 0变1)

比如:将00000000 00000000 00000000 00000101每一位取反,得11111111 11111111 11111111 11111010。

称:11111111 11111111 11111111 11111010 是 00000000 00000000 00000000 00000101 的反码。

反码是相互的,所以也可称:

11111111 11111111 11111111 11111010 和 00000000 00000000 00000000 00000101 互为反码。

补码:反码加1称为补码。

也就是说,要得到一个数的补码,先得到反码,然后将反码加上1,所得数称为补码。

比如:00000000 00000000 00000000 00000101 的反码是:11111111 11111111 11111111 11111010。

那么,补码为:

11111111 11111111 11111111 11111010 + 1 = 11111111 11111111 11111111 11111011

所以,-5 在计算机中表达为:11111111 11111111 11111111 11111011。转换为十六进制:0xFFFFFFFB。

再举一例,我们来看整数-1在计算机中如何表示。

假设这也是一个int类型,那么:

1、先取1的原码:00000000 00000000 00000000 00000001

2、得反码: 11111111 11111111 11111111 11111110

3、得补码: 11111111 11111111 11111111 11111111

可见,-1在计算机里用二进制表达就是全1。16进制为:0xFFFFFF。

码、反码、补码

结束了各种进制的转换,我们来谈谈另一个话题:原码、反码、补码。

我们已经知道计算机中,所有数据最终都是使用二进制数表达。

我们也已经学会如何将一个10进制数如何转换为二进制数。

不过,我们仍然没有学习一个负数如何用二进制表达。

比如,假设有一 int 类型的数,值为5,那么,我们知道它在计算机中表示为:

00000000 00000000 00000000 00000101

5转换成二制是101,不过int类型的数占用4字节(32位),所以前面填了一堆0。

现在想知道,-5在计算机中如何表示?

在计算机中,负数以其正值的补码形式表达。

什么叫补码呢?这得从原码,反码说起。

原码:一个整数,按照绝对值大小转换成的二进制数,称为原码。

比如 00000000 00000000 00000000 00000101 是 5的原码。

反码:将二进制数按位取反,所得的新二进制数称为原二进制数的反码。

取反操作指:原为1,得0;原为0,得1。(1变0; 0变1)

比如:将00000000 00000000 00000000 00000101每一位取反,得11111111 11111111 11111111 11111010。

称:11111111 11111111 11111111 11111010 是 00000000 00000000 00000000 00000101 的反码。

反码是相互的,所以也可称:

11111111 11111111 11111111 11111010 和 00000000 00000000 00000000 00000101 互为反码。

补码:反码加1称为补码。

也就是说,要得到一个数的补码,先得到反码,然后将反码加上1,所得数称为补码。

比如:00000000 00000000 00000000 00000101 的反码是:11111111 11111111 11111111 11111010。

那么,补码为:

11111111 11111111 11111111 11111010 + 1 = 11111111 11111111 11111111 11111011

所以,-5 在计算机中表达为:11111111 11111111 11111111 11111011。转换为

十六进制:0xFFFFFFFB。

再举一例,我们来看整数-1在计算机中如何表示。

假设这也是一个int类型,那么:

1、先取1的原码:00000000 00000000 00000000 00000001

2、得反码: 11111111 11111111 11111111 11111110

3、得补码: 11111111 11111111 11111111 11111111

可见,-1在计算机里用二进制表达就是全1。16进制为:0xFFFFFF。

计算机原理-原码、反码、补码

更多内容:https://www.360docs.net/doc/7e7596321.html,/jsjyuanli/200701/7687.html

首先要说的是:计算机中的带符号数一般用补码表示

计算机中的带符号数用补码表示的优点:

1、负数的补码与对应正数的补码之间的转换可以用同一种方法——求补运算完成,可以简化硬件;

2、可将减法变为加法,省去减法器;

3、无符号数及带符号数的加法运算可以用同一电路完成。

带符号数的表示

先引进两个名词:机器数和真值。

将一个数在机器中的表示形式,即编码称为机器数,数的本身称为真值。平常我们经常用的带符号的数就是真数,如:+50,-10.5等等。

常用的机器数有三种:原码、补码和反码。

1.原码

通俗定义

将数的符号数码化,即用一个二进制位表示符号:对正数,该位取0,对负数,该位取1。

而数值部分保持数的原有形式(有时需要在高位部分添几个0)。这样所得结果为该数的原码表示。

例,x=+1001010,y= -1001010,z= 一1110(= 一0001110)。当原码为8位时,x、y和z的原码分别是:

[x]原=01001010;

[y]原=11001010;

[Z]原=10001110.

其中最高位为符号位。

2)正规定义

2.反码

反码:正数的反码为原码,负数的反码是原码符号位外按位取反。

例如:

X1=+67=+100 0011B ,[X1]反=0100 0011B

X2=-67=-100 0011B ,[X2]反=1011 1100B

对正数,其反码与原码相同,也与补码相同。对负数,其反码等于原码除符号位外,按位求反(末位不加1)。利用反码也可使带符号数的加、减法转化为单纯的加法,但麻烦一些。

一般把求反码作为求补的中间过程,即 [x]补=[x]反+1。

3.补码

1)补码的引进和定义

据统计,在所有的运算中,加、减运算要占到80%以上,因此,能否方便地进行正、负数加、减运算,直接关系到计算机的运行效率。把一个负数加模的结果称为该负数的补码(结果是一个正数,它和该负数是等价的,确切地说,是一对一的,因而可看作是该负数的编码),定义正数的补码就是它本身,符号位取0,即和原码相同。这就是补码的通俗定义。将这个定义用数学形式表示出来,就可得到补码的正

规定义:

其中n为补码的位数。这个定义实际也将真值的范围给出来了,当n=8时,一27≤x<27。和原码相比,补码表示可多表示一个数。当n=8时,多表示的数是一27=一128。

2)补码的求法

对正数,补码同原码。

例如,x=+0101001,[x]补=[x]原=00101001。

对负数,由定义求补码,需做减法,不方便。经推导可知,负数的补码等于其原码除符号位外按位“求反”(1变0,0变1),末位再加1。

例如,y=一0001100,[y]原=10001100,[Y]补

=11110011+1=11110100。

?

算法:

1.正数的补码与原码相同;

2.负数的补码由原码除符号位保持不变外,其余各位按位取反,再在末位加1。

[x]补=[x]反+1

?

多做几例,可得出一种心算求补的方法——从最低位开始至找到的第一个1均不变,符号位不变,这之间的各位“求反”(该方法仅用于做题)。

C语言有符号数与无符号数之间的转换

C语言有符号数与无符号数之间的转换 无符号数:不存在正负之分,所有位都用来表示数的本身。 有符号数:最高位用来表示数的正负,最高位为1则表示负数,最高位为0则表示正数。 1.无符号数--->有符号数 看无符号数的最高位是否为1,如果不为1(为0),则有符号数就直接等于无符号数;如果无符号数的最高位为1,则将无符号数取补码,得到的数就是有符号数。 以unsigned char 和char为例子: 1.1将无符号数2转为有符号数 2的原码是:0000 0010,可知最高位不为1,因此转为有符号数之后也是2。 程序: 1 #include 2 3int main(void) 4{ 5 unsigned char i = 2; 6 7 printf("%d/n",(char)i); 8 9return0;10} 运行结果: 1.2将无符号数130转为有符号数 130的原码是:1000 0010,可知最高位为1,因此需要取它的补码,补码为1111 1110,这是一个负数,取最高位作为-号,取最低7位作为数值得到的结果是-126。 程序: 1 #include 2 3int main(void) 4{ 5 unsigned char i = 130; 6 7 printf("%d/n",(char)i); 8 9return0;10 } 运行结果: 2.有符号数--->无符号数 看有符号数的最高位是否为1,如果不为1(为0),则无符号数就直接等于有符号数;如果有符号数的最高位为1,则将有符号数取补码,得到的数就是无符号数。 以char 和unsigned char为例子: 2.1将有符号数3转为无符号数 3的原码是:0000 0011,可知最高位不为1,因此转为无符号数之后也是3。 程序: 1 #include 2 3int main(void) 4{ 5char i = 3; 6 7 printf("%u/n",(unsigned char)i); 8 9return0;10 } 运行结果: 2.2将有符号数-7转为无符号数 -7的原码是:1000 0111,可知最高位为1,因此需要取它的补码,补码为1111 1001,这是一个正数,因此整个数的值就是249。 程序: 1 #include 2 3int main(void) 4{ 5char i = -7; 6 7 printf("%u/n",(unsigned char)i); 8 9return0;10 } 运行结果:

理解C语言有符号数和无符号数

声明网上看到的文章,原文找不到了,原文被转载的不成样子,重复很多,整理花了很长时间,在翻看了维基百科后发现,原文中对于负数原码和补码存在一些问题,修改了一部分,原作者看到后可以联系我。 1、你自已决定是否需要有正负。 就像我们必须决定某个量使用整数还是实数,使用多大的范围数一样,我们必须自已决定某个量是否需要正负。如果这个量不会有负值,那么我们可以定它为带正负的类型。 在计算机中,可以区分正负的类型,称为有符类型(signed),无正负的类型(只有正值),称为无符类型。(unsigned)数值类型分为整型或实型,其中整型又分为无符类型或有符类型,而实型则只有符类型。字符类型也分为有符和无符类型。比如有两个量,年龄和库存,我们可以定前者为无符的字符类型,后者定为有符的整数类型。 2、使用二制数中的最高位表示正负。 首先得知道最高位是哪一位?1个字节的类型,如字符类型,最高位是第7位,2个字节的数,最高位是第15位,4个字节的数,最高位是第31位。不同长度的数值类型,其最高位也就不同,但总是最左边的那位(如下示意)。字符类型固定是1个字节,所以最高位总是第7位。 (红色为最高位) 单字节数:11111111 双字节数: 11111111 11111111 四字节数:11111111 11111111 11111111 11111111 当我们指定一个数量是无符号类型时,那么其最高位的1或0,和其它位一样,用来表示该数的大小。 当我们指定一个数量是无符号类型时,此时,最高数称为“符号位”。为1时,表示该数

为负值,为0时表示为正值。 3、无符号数和有符号数的范围区别。 无符号数中,所有的位都用于直接表示该值的大小。有符号数中最高位用于表示正负,所以,当为正值时,该数的最大值就会变小。我们举一个字节的数值对比: 无符号数:11111111 值:255 1* 27 + 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20 有符号数:01111111 值:127 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20 同样是一个字节,无符号数的最大值是255,而有符号数的最大值是127。原因是有符号数中的最高位被挪去表示符号了。并且,我们知道,最高位的权值也是最高的(对于1字节数来说是2的7次方=128),所以仅仅少于一位,最大值一下子减半。 不过,有符号数的长处是它可以表示负数。因此,虽然它的在最大值缩水了,却在负值的方向出现了伸展。我们仍一个字节的数值对比: 无符号数:0 ----------------- 255 有符号数:-128 --------- 0 ---------- 127 同样是一个字节,无符号的最小值是0 ,而有符号数的最小值是-128。所以二者能表达的不同的数值的个数都一样是256个。只不过前者表达的是0到255这256个数,后者表达的是-128到+127这256个数。 一个有符号的数据类型的最小值是如何计算出来的呢? 有符号的数据类型的最大值的计算方法完全和无符号一样,只不过它少了一个最高位(见第3点)。但在负值范围内,数值的计算方法不能直接使用1* 26 + 1* 25 的公式进行转换。在计算机中,负数除为最高位为1以外,还采用补码形式进行表达。所以在计算其值前,

无符号数、有符号数、原码、反码、补码——数据在计算机内部的表示

数据在计算机内部的表示与存储 作者:刘英皓 2013/4/17 今天在做单片机实验的时候,突然对一个问题产生了浓厚的兴趣:数据在计算机内部是怎么表示的?晚上查阅了大量的资料,终于把其中的玄机弄明白了。 资料来源甚广,在此就不一一声明了,感谢!! 数据是什么?它是用来表示信息的。是信息的载体。比如数值、文字、语言、图形、影像等都是不同形式的数据。而在计算机中,无论是数值型数据还是非数值型数据,它们都被表示成了0和1。 既然都变成了0和1,那计算机怎么区别这些不同的信息呢?别担心,它们各在有各自的编码规则。非数值型数据的编码主要有ASCII 码和汉字编码。这里不深究。 数值型数据:它主要有两种形式,有符号数和无符号数 1、有符号数和无符号数 它们的定义估计你都听腻了,我就不重复了,我只强调两点: a.计算机不区分有符号数和无符号数。 b.只有有符号数才有原码、反码和补码。 2、原码、反码和补码 还是两点:

a.正数的原码、反码和补码都一样。 b.负数的反码为原码除符号位的按位取反,补码为反码加1. 注意两点: b1.反码1111 1111的补码是0000 0000. b2.补码1000 0000没有对应的原码和反码,它表示-128,这是规定 3、计算机存储单元中的数据 这个要分两种情况: a.无符号数:直接以对应的二进制表示。 b.有符号数:补码形式表示,无论是计算还是存取。 比如在内存单元中有一个数据为FEH,那么它到底是表示什么?254还是-2?没关系,你说是什么就是什么。因为计算机是不会区分这个数是有符号数还是无符号数的。在你写程序的时候,指定这个量是有符号的,FEH就是一个补码,可以计算得它的真值就是-2,如果指定它是无符号的,那么它就是254。不同的形式在程序中便会有不同的体现。要注意的是在计算中不要超出了数值的范围,以免发生错误。 如有疑问请联系:yinghao1991@https://www.360docs.net/doc/7e7596321.html,

无符号数除法

在Verilog HDL语言中虽然有除的运算指令,但是除运算符中的除数必须是2的幂,因此无法实现除数为任意整数的除法,很大程度上限制了它的使用领域。并且多数综合工具对于除运算指令不能综合出令人满意的结果,有些甚至不能给予综合。对于这种情况,一般使用相应的算法来实现除法,分为两类,基于减法操作和基于乘法操作的算法。[1] 基于减法的除法器的算法: 对于32的无符号除法,被除数a除以除数b,他们的商和余数一定不会超过32位。首先将a转换成高32位为0,低32位为a的temp_a。把b转换成高32位为b,低32位为0的temp_b。在每个周期开始时,先将temp_a左移一位,末尾补0,然后与b比较,是否大于b,是则temp_a减去temp_b将且加上1,否则继续往下执行。上面的移位、比较和减法(视具体情况而定)要执行32次,执行结束后temp_a的高32位即为余数,低32位即为商。 Verilog HDL 代码 /* 功能:32位除法器 输入参数:被除数a,除数b 输出参数:商yshang,余数yyushu 备注:采用移位、比较和减法(从高位开始)实现的除法运算 本例实现的是32位除法器的例子 */ module division(a,b,yshang,yyushu); input[31:0] a; //被除数 input[31:0] b; //除数 output[31:0] yshang; // output[31:0] yyushu; // reg[31:0] yshang; reg[31:0] yyushu; reg[31:0] tempa; reg[31:0] tempb; reg[63:0] temp_a; reg[63:0] temp_b; always @(a or b) begin tempa <= a; tempb <= b; end integer i;

有符号数与无符号数

1、你自已决定是否需要有正负。 就像我们必须决定某个量使用整数还是实数,使用多大的范围数一样,我们必须自已决定某个量是否需要正负。如果这个量不会有负值,那么我们可以定它为带正负的类型。 在计算机中,可以区分正负的类型,称为有符类型,无正负的类型(只有正值),称为无符类型。 数值类型分为整型或实型,其中整型又分为无符类型或有符类型,而实型则只有符类型。 字符类型也分为有符和无符类型。 比如有两个量,年龄和库存,我们可以定前者为无符的字符类型,后者定为有符的整数类型。 2、使用二制数中的最高位表示正负。 首先得知道最高位是哪一位?1个字节的类型,如字符类型,最高位是第7位,2个字节的数,最高位是第15位,4个字节的数,最高位是第31位。不同长度的数值类型,其最高位也就不同,但总是最左边的那位(如下示意)。字符类型固定是1个字节,所以最高位总是第7位。 (红色为最高位) 单字节数:1111 1111 双字节数:1111 1111 1111 1111 四字节数:1111 1111 1111 1111 1111 1111 1111 1111 当我们指定一个数量是无符号类型时,那么其最高位的1或0,和其它位一样,用来表示该数的大小。 当我们指定一个数量是无符号类型时,此时,最高数称为“符号位”。为1时,表示该数为负值,为0时表示为正值。 3、无符号数和有符号数的范围区别。 无符号数中,所有的位都用于直接表示该值的大小。有符号数中最高位用于表示

正负,所以,当为正值时,该数的最大值就会变小。我们举一个字节的数值对比: 无符号数: 1111 1111 值:255 1* 27 + 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20 有符号数: 0111 1111 值:127 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20 同样是一个字节,无符号数的最大值是255,而有符号数的最大值是127。原因是有符号数中的最高位被挪去表示符号了。并且,我们知道,最高位的权值也是最高的(对于1字节数来说是2的7次方=128),所以仅仅少于一位,最大值一下子减半。 不过,有符号数的长处是它可以表示负数。因此,虽然它的在最大值缩水了,却在负值的方向出现了伸展。我们仍一个字节的数值对比: 无符号数: 0 ----------------- 255 有符号数: -128 --------- 0 ---------- 127 同样是一个字节,无符号的最小值是 0 ,而有符号数的最小值是-128。所以二者能表达的不同的数值的个数都一样是256个。只不过前者表达的是0到255 这256个数,后者表达的是-128到+127这256个数。 一个有符号的数据类型的最小值是如何计算出来的呢? 有符号的数据类型的最大值的计算方法完全和无符号一样,只不过它少了一个最高位(见第3点)。但在负值范围内,数值的计算方法不能直接使用1* 26+ 1* 25的公式进行转换。在计算机中,负数除为最高位为1以外,还采用补码形式进行表达。所以在计算其值前,需要对补码进行还原。这些内容我们将在第六章中的二进制知识中统一学习。 这里,先直观地看一眼补码的形式: 以我们原有的数学经验,在10进制中:1 表示正1,而加上负号:-1 表示和1相对的负值。 那么,我们会很容易认为在2进制中(1个字节): 0000 0001 表示正1,则高位为1后:1000 0001应该表示-1。 然而,事实上计算机中的规定有些相反,请看下表:

无符号大整数计算器

C语言及面向对象程序设计实验石家庄铁道大学信息学院 A 数学类 1.题目要求: 高斯消元法求解线性方程组:在线性代数中,学习过用高斯消元法求解线性方程组,用类来实现该方法,并在主函数中进行测试; 2.解题思路: 通常应用高斯消元法的时候,不会直接写出方程组的等式来消去未知数,反而会使用矩阵来计算,将其转化为行阶梯式矩阵,所以程序的算法即线性代数中的矩阵变换为行阶梯式矩阵步骤,所以用一个二维数组存放系数矩阵,一个一维数组存放解值。 3.类的结构(数据和函数); //gauss.h #pragma once #include #include #define N 100 using namespace std; class gauss { private: double a[N][N],b[N]; public: gauss(void); void setvalue(int ); ~gauss(void); }; //gauss.cpp #include "gauss.h" gauss::gauss(void) { }

void gauss::setvalue(int n) { int i,j,k; double a[N][N]; cout<<"请输入"<>a[i][j]; double o,b[N]; for (i=1;i<=n;i++) for (j=i+1;j<=n;j++) if (fabs(a[j][i])>1e-7) { o=a[i][i]/a[j][i]; for (k=i;k<=n+1;k++) a[j][k]=a[j][k]*o-a[i][k]; } for (i=n;i>0;i--) { b[i]=a[i][n+1]/a[i][i]; for (j=i-1;j>0;j--) a[j][n+1]=a[j][n+1]-b[i]*a[j][i]; } cout<<"解得:"< #include #include "gauss.h" using namespace std; void main() { int n; cout<<"请输入未知数个数:"<

Verilog带符号数运算

Verilog带符号数运算 摘要:介绍了Verilog带符号数的不同运算。因为Reg和Wire数据默认情况下是无符号的,而在数据处理的情况下,Verilog既要对带符号数据进行各种运算,也要对无符号数和带符号数进行运算,所以简单使用Verilog提供的运算符是不够的。因此研究不同类型数据运算的通用方法是必要的。 关键词:Verilog;带符号数;补码;算术运算 中图分类号:TN911?34 文献标识码:A 文章编号:1004?373X(2015)03?0160?03 Operation of numbers with symbols by Verilog HUI Wei?jun,SHEN Zhao?jun (Yancheng Institute of Technology,Yancheng 224051,China) Abstract:Different operations of data with symbols by Verilog are introduced. Reg and Wire data in the case of default is unsigned,but in the case of data processing,a variety of operations of data with symbols are performed by Verilog,and the unsigned and signed with numbers need to be processed. However,it is not enough to use the operation symbols provided by Verilog. It is necessary to research the general

有符号数与无符号数的探讨

有符号数与无符号数的探讨 这个问题,要是简单的理解,是很容易的,不过要是考虑的深了,还真有些东西呢。 下面我就把这个东西尽量的扩展一点,深入一点和大家说说。 一、只有一个标准! 在汇编语言层面,声明变量的时候,没有si g ned和u nsi gn d e之分,汇编器统统,将你输入的整数字面量当作有符号数处理成补码存入到计算机中,只有这一个标准!汇编器不会区分有符号还是无符号然后用两个标准来处理,它统统当作有符号的!并且统统汇编成补码!也就是说,d b-20汇编后为:EC,而d b236汇编后也为EC。这里有一个小问题,思考深入的朋友会发现,db是分配一个字节,那么一个字节能表示的有符号整数范围是:-128~+ 127,那么d b236超过了这一范围,怎么可以?是的,+236的补码的确超出了一个字节的表示范围,那么拿两个字节(当然更多的字节更好了)是可以装下的,应为:00EC,也就是说+236的补码应该是00EC,一个字节装不下,但是,别忘了“截断”这个概念,就是说最后汇编的结果被截断了,00EC是两个字节,被截断成EC,所以,这是个“美丽的错误”,为什么这么说?因为,当你把236当作无符号数时,它汇编后的结果正好也是EC,这下皆大欢喜了,虽然汇编器只用一个标准来处理,但是借用了“截断”这个美丽的错误后,得到的结果是符合两个标准的!也就是说,给你一个字节,你想输入有符号的数,比如-20那么汇编后的结果是符合有符号数的;如果你输入236那么你肯定当作无符号数来处理了(因为236不在一个字节能表示的有符号数的范围内啊),得到的结果是符合无符号数的。于是给大家一个错觉:汇编器有两套标准,会区分有符号和无符号,然后分别汇编。其实,你们被骗了。:-) 二、存在两套指令! 第一点说明汇编器只用一个方法把整数字面量汇编成真正的机器数。但并不是说计算机不区分有符号数和无符号数,相反,计算机对有符号和无符号数区分的十分清晰,因为计算机进行某些同样功能的处理时有两套指令作为后备,这就是分别为有符号和无符号数准备的。但是,这里要强调一点,一个数到底是有符号数还是无符号数,计算机并不知道,这是由你来决定的,当你认为你要处理的数是有符号的,那么你就用那一套处理有符号数的指令,当你认为你要处理的数是无符号的,那就用处理无符号数的那一套指令。加减法只有一套指令,因为这一套指令同时适用于有符号和无符号。下面这些指令:m ul di v m ovz x…是处理无符号数的,而这些:i m ul i di v

带符号数的原码、反码与补码分析

一.带符号数的原码、反码与补码 所谓带符号数,其实就是一个二进制数据,它的最高位所代表的是符号,其余位是其“绝对值”。例如0101_0011,这个数据如果是带符号数,那么最高位的0就是代表这个数据为正数,其后的101-0011则代表这个数据的绝对值,为+83D。如果是1101_0011,则代表-83D。 1.1 原码 原码就是按照正数的符号位为0,负数的符号位为1,其他位就是数据的绝对值即可。例如当机器字长为8bit的二进制数时,它的最高位为符号位,因此其余的7bit位数据的绝对值。因此原码所能表示的数据范围是: - (2n-1-1)~+(2n-1-1) 当字长为8bit,则原码能表示的范围就是:-127~+127 例如83的原码就是:0101_0011 当字长为16bit,则原码能表示的范围就是:-32767~+32767 例如-83的原码就是:1000_0000_0101_0011 1.2 反码 对于一个带有符号位的二进制数来说,正数的反码与其原码相同,负数的反码为其原码除符号位外其余各位按位取反。 例如当字长为8bit时,+83D的反码就是:0101_0011,-83D的反码就是1010_1100 负数的反码与原码有很大的差别,一般情况下,反码主要用来当做求二进制数补码的中间形式。反码所表示的数据范围与原码相同: - (2n-1-1)~+(2n-1-1) 1.2 补码 正数的补码与其原码相同,负数的补码为其反码在最低位加1。 例如: X=+101_1011 [X]原码=0101_1011 [X]补码=0101_1011 X=-101_1011 [X]原码=1101_1011 [X]补码=1010_0101 补码表示的范围是: - 2n-1~+(2n-1-1)

计算机组成原理_计算机的运算方法_61 无符号数和有符号数_

6.1 无符号数和有符号数

寄存器的位数 反映无符号数的表示范围 8 位 0 ~ 255 16 位 0 ~ 65535

带符号的数 符号数字化的数 + 0.10110 1011小数点的位置+ 11000 1100 小数点的位置– 1100 1 1100 小数点的位置 – 0.10111 1011 小数点的位置真值 机器数 1. 机器数与真值

2. 原码表示法—整数 带符号的绝对值表示 x 为真值n 为整数的位数 如x = +1110 [x ]原 = 0 , 1110 [x ]原 = 24 + 1110 = 1 , 1110 x = 1110[x ]原 = 0,x 2n > x ≥ 0 2n x 0 ≥ x > 2 n 用 逗号 将符号位和数值部分隔开

x 为真值 如x = + 0.1101 [x ]原 = 0 . 1101 x = – 0.1101[x ]原 = 1 – (–0.1101) = 1 . 1101 x 1 > x ≥ 0 [x ]原 = 1 – x 0 ≥ x >–1 x = – 0.1000000 [x ]原 = 1 – (– 0.1000000) = 1 . 1000000 x = + 0.1000000[x ]原 = 0 . 1000000 用 小数点 将符号位和数值部分隔开 用 小数点 将符号位和数值部分隔开 2. 原码表示法—小数

例 6.1 已知 [x ]原 = 1.0011 求 x 解:例 6.2 已知 [x ]原 = 1,1100 求 x 解:x = 1 – [x ]原 = 1 – 1.0011 = –0.0011 x = 24 – [x ]原 = 10000 – 1,1100 = –1100 – –0.0011 1100由定义得 由定义得

无符号数词法分析程序

#include #include #include #define DIGIT 1 #define POINT 2 #define OTHER 3 #define POWER 4 #define PLUS 5 #define MINUS 6 #define UCON 7 //Suppose the class number of unsigned constant is 7 #define ClassOther 200 #define EndState -1 int w,n,p,e,d; int Class; //Used to indicate class of the word int ICON; float FCON; static int CurrentState; //Used to present current state, the initial value:0 int GetChar (void); int EXCUTE (int,int); int LEX (void); //_____________________________________________________________________________ _________________________ int HandleOtherWord (void) { return ClassOther; } //_____________________________________________________________________________ __________________________ int HandleError (void) {printf ("Error!\n"); return 0;} //_____________________________________________________________________________ __________________________ int GetChar (void) { int c; c=getchar( ); if(isdigit(c)) {d=c-'0';return DIGIT;} if (c=='.') return POINT; if (c=='E'||c=='e') return POWER; if (c=='+') return PLUS; if (c=='-') return MINUS;

关于有符号数、无符号数和数据类型的总结

一、 CPU只会根据输入信号进行逻辑运算,在硬件级别是没有有符号无符号的概念,运算结束会根据运算前的信号和输出信号来设置一些标志位,是不是有符号由写程序的人决定,标志位要看你把操作数当有符号还是无符号来选择,就像内存中的数据,你可以按照需要来解析,原始数据在那里,你要按什么数据格式来解析在于自己的选择,所以玩汇编的要做到心里有数,加减法只有一套指令,因为这一套指令同时适用于有符号和无符号。下面这些指令:mul div movzx … 是处理无符号数的,而这些:imul idiv movsx … 是处理有符号的。举例来说:内存里有一个字节x 为:0x EC ,一个字节y 为:0x 02 。当把x,y当作有符号数来看时,x = -20 ,y = +2 。当作无符号数看时,x = 236 ,y = 2 。下面进行加运算,用add 指令,得到的结果为:0x EE ,那么这个0x EE 当作有符号数就是:-18 ,无符号数就是238 。所以,add 一个指令可以适用有符号和无符号两种情况。(呵呵,其实为什么要补码啊,就是为了这个呗,:-)) 乘法运算就不行了,必须用两套指令,有符号的情况下用imul 得到的结果是:0x FF D8 就是-40 。无符号的情况下用mul ,得到:0x 01 D8 就是472 。 二、 C又是可怕的,因为它把机器层面的所有的东西都反应了出来,像这个有没有符号的问题就是一例(java就不存在这个问题,因为它被设计成所有的整数都是有符号的)。为了说明c的可怕特举一例: #include #include int main() { int x = 2; char * str = "abcd"; int y = (x - strlen(str) ) / 2; printf("%d\n",y);

汇编中有符号与无符号数的区分

汇编中有符号与无符号数的区分 一、只有一个标准! 在汇编语言层面,声明变量的时候,没有signed 和unsignde 之分,汇编器统统,将你输入的整数字面量当作有符号数处理成补码存入到计算机中,只有这一个标准!汇编器不会区分有符号还是无符号然后用两个标准来处理,它统统当作有符号的!并且统统汇编成补码!也就是说,db -20 汇编后为:EC ,而db 236 汇编后也为EC 。这里有一个小问题,思考深入的朋友会发现,db 是分配一个字节,那么一个字节能表示的有符号整数范围是:-128 ~ +127 ,那么db 236 超过了这一范围,怎么可以?是的,+236 的补码的确超出了一个字节的表示范围,那么拿两个字节(当然更多的字节更好了)是可以装下的,应为:00 EC,也就是说+236的补码应该是00 EC,一个字节装不下,但是,别忘了“截断”这个概念,就是说最后的结果被截断了,00 EC 是两个字节,被截断成EC ,所以,这是个“美丽的错误”,为什么这么说?因为,当你把236 当作无符号数时,它汇编后的结果正好也是EC ,这下皆大欢喜了,虽然汇编器只用一个标准来处理,但是借用了“截断”这个美丽的错误后,得到的结果是符合两个标准的!也就是说,给你一个字节,你想输入有符号的数,比如-20 那么汇编后的结果是正确的;如果你输入236 那么你肯定当作无符号数来处理了(因为236不在一个字节能表示的有符号数的范围内啊),得到的结果也是正确的。于是给大家一个错觉:汇编器有两套标准,会区分有符号和无符号,然后分别汇编。其实,你们被骗了。:-) 二、存在两套指令! 第一点说明汇编器只用一个方法把整数字面量汇编成真正的机器数。但并不是说计算机不区分有符号数和无符号数,相反,计算机对有符号和无符号数区分的十分清晰,因为计算机进行某些同样功能的处理时有两套指令作为后备,这就是分别为有符号和无符号数准备的。但是,这里要强调一点,一个数到底是有符号数还是无符号数,计算机并不知道,这是由你来决定的,当你认为你要处理的数是有符号的,那么你就用那一套处理有符号数的指令,当你认为你要处理的数是无符号的,那就用处理无符号数的那一套指令。加减法只有一套指令,因为这一套指令同时适用于有符号和无符号。下面这些指令:mul div movzx …是处理无符号数的,而这些:imul idiv movsx …是处理有符号的。 举例来说: 内存里有一个字节x 为:0x EC ,一个字节y 为:0x 02 。当把x,y当作有符号数来看时,x = -20 ,y = +2 。当作无符号数看时,x = 236 ,y = 2 。下面进行加运算,用add 指令,得到的结果为:0x EE ,那么这个0x EE 当作有符号数就是:-18 ,无符号数就是238 。所以,add 一个指令可以适用有符号和无符号两种情况。(呵呵,其实为什么要补码啊,就

无符号数的识别

无符号数的词法分析程序 一、实验目的和要求 (1)初步掌握编译原理的实验的技能; (2)验证所学理论、巩固所学知识并加深理解。 二、实验内容和原理 内容:掌握词法分析的基本思想,并用高级语言编写无符号数(包括整数和实数)的词法分析程序。 要求:从键盘中输入一字符串(包括字母、数字等),编写程序识别出其中的无符号数。 无符号数的文法规则课定义如下: <无符号数> <无符号实数>|<无符号整数> <无符号实数> <无符号整数>.<数字串>[E<比例因子>] <比例因子> <有符号整数> <有符号整数> [+|-]<无符号整数> <无符号整数> <数字串> <数字串> <数字>{<数字>} <数字> 0 1 2 3 4 5 6 7 8 9 本实验中我利用了状态转化图的思想,下面是试验中用到构造的状态转化图:

字 描述状态机的代码格式如下: int state = S0 ; while(1) { Switch(state) { case S0 : if(T0转移条件满足) {状态转移到满足T0的次态;操作;} if(T1转移条件满足) {状态转移到满足T1的次态;操作;} if(T2转移条件满足) {状态转移到满足T2的次态;操作;} … Break ; case S1 : //插入S1状态下的操作; break ;

… } } 实验代码: //本程序主要实现实数的识别 import java.io.BufferedReader ; import java.io.IOException ; import java.io.InputStreamReader ; public class RealNumberIdentified { /*---------------------------------成员变量的定义---------------------------------------*/ private final int S_0 = 0 ; private final int S_1 = 1 ; private final int S_2 = 2 ; private final int S_3 = 3 ; private final int S_4 = 4 ; private final int S_5 = 5 ; private final int S_6 = 6 ; private final int S_7 = 7 ;

有符号数加法问题

有符号数加法问题 问题:两个8位数有符号相加,结果要求是16位。 解题思路:如果两个有符号数相加没有溢出,则将加法的结果通过CBW指令扩展成16位。如果加法产生了溢出,则判断加法是否产生了进位,如果没有产生进位,说明这两个有符号数都是正数,此时,在8位的结果前补上00H,将其变成16位的结果;如果产生了进位,说明这两个有符号数都是负数,此时,在8位结果前补上FFH,将其变成16位的结果。 举例: ●两个有符号数01H(真值为1)和02H(真值为2)做加法运算, 因为-128≦1+2≦127,这说明两数相加不会产生溢出,加法的结果为03H(真值为3),通过CBW指令进行扩展,得到16位的结果0003H(真值为3)。 ●两个有符号数F6H(真值为-10)和F5H(真值为-11)做加法运 算,因为-128≦(-10)+(-11)≦127,这说明两数相加不会产生溢出,加法的结果为EBH(真值为-21),通过CBW指令进行扩展,得到16位的结果FFEBH(真值为-21)。 ●两个有符号数64H(真值为100)和65H(真值为101)做加法运 算,因为100+101≧127,这说明两数相加后会产生溢出,加法的结果为C9H(真值为-55),此时加法没有产生进位,说明两个加数都是正数,在C9H前补上00H得到16位的结果00C9H(真值为201)。

两个有符号数9CH(真值为-100)和9BH(真值为-101)做加法运算,因为(-100)+(-101)≦-128,这说明两数相加后会产生溢出,加法的结果为37H(真值为55),此时加法产生了进位,说明两个加数都是负数,在37H前补上FFH得到16位的结果FF37H(真值为-201)。 通过程序解决该问题(被加数和加数分别放在AL和BL寄存器中,16位的结果放AX中) ADD AL, BL JO OVERFLOW ;如产生溢出,则转移到OVERFLOW CBW ;该指令不会影响任何标志位 JMP NEXT OVERFLOW: JC L1 ;产生进位说明两个数都是负数AND AH, 00H JMP NEXT L1: OR AH, FFH NEXT: …..

【推荐】C语言中有符号数与无符号数解析

C语言中有符号数,与无符号数的辨析 关于有符号数,无符号数,你可能听过两种不同的回答。一种是教科书,它会告诉你:计算机用“补码”表示负数。可是有关“补码”的概念一说就得一节课,这一些我们需要在第6章中用一章的篇幅讲2进制的一切。再者,用“补码”表示负数,其实一种公式,公式的作用在于告诉你,想得问题的答案,应该如何计算。却并没有告诉你为什么用这个公式就可以和答案? 另一种是一些程序员告诉你的:用二进制数的最高位表示符号,最高位是0,表示正数,最高位是1,表示负数。这种说法本身没错,可是如果没有下文,那么它就是错的。至少它不能解释,为什么字符类型的-1用二进制表示是“1111 1111”(16进制为FF);而不是我们更能理解的“10000001”。(为什么说后者更好理解呢?因为既然说最高位是1时表示负数,那10000001不是正好是-1吗?)。 让我们从头说起。 1、你自已决定是否需要有正负。 就像我们必须决定某个量使用整数还是实数,使用多大的范围数一样,我们必须自已决定某个量是否需要正负。在计算机中,可以区分正负的类型,称为有符类型,无正负的类型(只有正值),称为无符类型。 数值类型分为整型或实型,其中整型又分为无符类型或有符类型,而实型则只有有符类型。 字符类型也分为有符和无符类型。 2、使用二制数中的最高位表示正负。 首先得知道最高位是哪一位?1个字节的类型,如字符类型,最高位是第7位,2个字节的数,最高位是第15位,4个字节的数,最高位是第31位。不同长度的数值类型,其最高位也就不同,但总是最左边的那位(如下示意)。字符类型固定是1个字节,所以最高位总是第7位。 (红色为最高位) 单字节数:11111111 双字节数:1111111111111111 四字节数:11111111111111111111111111111111 当我们指定一个数量是无符号类型时,那么其最高位的1或0,和其它位一样,用来表示该数的大小。 当我们指定一个数量是无符号类型时,此时,最高数称为“符号位”。为1时,表示该数为负值,为0时表示为正值。 3、无符号数和有符号数的范围区别。 无符号数中,所有的位都用于直接表示该值的大小。有符号数中最高位用于表示正负,所以,当为正值时,该数的最大值就会变小。我们举一个字节的数值对比:

8位有符号数的表示范围

为什么8位有符号数的范围是“-128 至+127” 这是一个困惑了我几年的问题,它让我对现在的教科书和老师极其不满,从我 N年前开始摸电脑时,就几乎在每一本C++教科书上都说,8 位有符号的取值范围是-128~+127,为什么不是-127~+127呢,后来的java,int 的聚值范围,再32 位计 算,-2^31 ~ +2^31-1,可是,却从来没有任何一本教科书或一个老师比我解释过这个问题。原因没有在工作上或者是什么地方直接遇到它,所以我也一直忽略它,但心里总是有一根刺.直到刚才!!!! 就是刚才,无聊之极,在看汇编的书时,又遇到它了,但一如以往,书上直接地,有心地,明显地绕过了这个问题,真是可恶啊. 几经周折,终于把它搞清楚了: 其实它是计算机底层为了实现数值运算而决定的,涉及非常基础的源码,反码,补码知识,一般用不上,但是计算机考试除外。 用2^8来表示无符号整数的话,全世界的理解都是0 - 255了,那么,有符号呢? 用 最高位表示符号,0 为+,1 为-,那么,正常的理解就是-127 至+127 了. 这就是原码了,值得一提的是,原码的弱点,有2 个0,即+0 和-0,还有就是,进行异 号相加或同号相减时,比较笨蛋,先要判断2个数的绝对值大小,然后进行加减操作, 最后运算结果的符号还要与大的符号相同. 于是乎,反码产生了,原因....略,反正,没过多久,反码就成为了过滤产物,也就是,后 来补码出现了. 补码的知识不说述,只说有关+127 和-128 的. 官方的定义[-2^(n-1),2(n-1)-1],补码的0 没有正负之分.原因呢?没有一本书上 有说,这也是我这么火的原因,但通过思考,google,再思考,很快找到答案: 首先,难不免干点白痴般地事情,穷举一下... 正数,原码跟补码一样 +127, 0111 1111 +126, 0111 1110 +125, 0111 1101 +124, 0111 1100 +123, 0111 1011 +122, 0111 1010 ... +4, 0000 0100 +3, 0000 0011 +2, 0000 0010 +1, 0000 0001 0, 0000 0000 (无正负之分) 下面是负数了,值,原码,符号位不变其它取反,+1 -1, 1000 0001, 1111 1110, 1111 1111 -3, 1000 0011, 1111 1100, 1111 1101 -4, 1000 0100, 1111 1011, 1111 1100

有符号整数 无符号整数

C语言中定义有符号整型:signed int x; 由于signed 可以省略,所以int x; 也是可以定义有符号整型变量x C语言中,有符号数与无符号数主要是由于是高位是否代表符号(正、负数)来决定的。有符号数是最高位(二进制位)代表符号,1代表是负数,0代表是正数,不管是正数还是负数都是以补码的形式存储与使用的。 (1)正数的补码:与原码相同。例如,+9的补码是00001001。 (2)负数的补码:符号位为1,其余位为该数绝对值的原码按位取反;然后整个数加1。 例如,-7的补码:因为是负数,则符号位为“1”,整个为10000111;其余7位为-7的绝对值+7的原码0000111按位取反为1111000;再加1,所以-7的补码是11111001。 整型数据即整数。 整型数据的分类 整型数据的一般分类如下: ?基本型:类型说明符为int,在内存中占2个字节。 ?短整型:类型说明符为short int或short。所占字节和取值范围均与基本型相同。 ?长整型:类型说明符为long int或long,在内存中占4个字节。 ?无符号型:类型说明符为unsigned。 无符号型又可与上述三种类型匹配而构成: ?无符号基本型:类型说明符为unsigned int或unsigned。 ?无符号短整型:类型说明符为unsigned short。 ?无符号长整型:类型说明符为unsigned long。 下表列出了C语言中各类整型数据所分配的内存字节数及数的表示范围。

整型数据在内存中的存放形式 如果定义了一个整型变量i: inti; i=10; 数值是以补码表示的: ?正数的补码和原码相同; ?负数的补码:将该数的绝对值的二进制形式按位取反再加1。 例如:求-10的补码:

相关文档
最新文档