有符号数与无符号数的除法(转载)

有符号数与无符号数的除法

 (2010-11-08 16:01:36)
标签: 

it

分类: IT
这样一个问题:
int a = -2; printf("%d,%d", a/4*4, a/4U*4);
打印出的是:0,-4
有符号数与无符号数做除法时,双方都转为无符号数再做除法;
-2在计算机中的存储形式为:0xff ff ff fe
作为无符号数除以4时,向右移2位(左边补零),中间结果为0x3f ff ff ff
之后乘以4时,向左移位(右边补零),结果为oxff ff ff fc
该数字表示有符号数-4,于是-4就被打印出来。
【转】 有关C语言中有符号/无符号数混合运算的小问题
2010年08月25日 星期三 18:51
转载自 yjpro
最终编辑 yjpro
这两天的工作需要涉及到对无符合数,有符号数作混合运算。

作了一些实验,发现自己写了这么多年的程序,以前对于符号数计算相关的理解居然仍存在一些盲点。

有符号数与无符号数混合运算可能有三种混合方式

1。操作数全为有符号数
如:

int a = -1;
int b = 2;
a + b;


2。操作数全为无符号数
如:

unsigned int a = (unsigned int)-1;
unsigned int b = 2;
a + b;


3。操作数混合了有符号数,无符号数
如:

int a = -1;
unsigned int b = 2;
a / b;


情形1和2就不用说了,因为运算中涉及的都是相同符号特征的操作数,计算过程中不会引起歧义。

而对于情形3,由于涉及到了符号特性相异的操作数,情况就有些复杂了。

这里先说一下,对于有些运算操作,是要区分有符号与无符号的情况的。比如有符号的除法与无符号

的除法,有符号的取模运算与无符号的取模运算,其计算语意是不同的,具体来说,有符号的除法在x86

平台上对应的汇编指令是idiv,而无符号的除法对应的则是div

对于另外一些操作运算,则是不区分有符号与无符号的,比如,加法,减法,乘法运算。

对于不同操作符与符号相关的情形可以通过下面的小程序来验证:

int main()
{

signed int n1 = 1;
signed int n2 = 2;
unsigned int u1 = 1;
unsigned int u2 = 2;

signed int a = n1 + n2;
unsigned int ua = u1 + u2;

signed int s = n1 - n2;
unsigned int us = u1 - u2;

signed int m = n1 * n2;
unsigned int um = u1 * u2;

signed int d = n1 / n2;
unsigned int d = u1 / u2;

signed int m = n1 % n2;
unsigned int um = u1 % u2;

return 0;
}


对这一段程序调用 g++ -S,生成相应的汇编文件,就会发现:

加法运算,无论是有符号还是无符号,对应的都是addl指令,

减法
运算,对应的都是subl指令,

乘法
运算,对应的都是imul指令,

有符号除法
运算对应的是idiv指令,无符号除法对应的则是 div指令,

有符号数取模运算会用到idiv指令,无符号取模用的则是div指令。

所以回到初始的问题,情形1和2的行为是容易预期的,因为所有操作数都具有同样的符号特性,直接就

可以得出采用相应符号特性的运算类型。

对于情形3,因为涉及到不同符号数的混合计算,在计算之前需要先对操作数进行规整化的动

作,规整的原则就是如果操作数中存在至少一个无符号数,则所有操作数都被转化为无符号数,

运算操作也采用相应的无符号操作符进行,计算完的结果也是一个无符号数。


举例来说:

(unsigned int)a / (signed int)b 会采用无符号除法进行,其实质相当于

(unsigned int)a / (unsigned int)b

计算结果也是一个无符号数。

再进一步,对于运算-2 / -1,如果采用有符号数运算,结果是1,采用无符号数运算,结果则是0

所以 (signed int)(-2) / (unsigned int)(-1)的结果就是0了。

除法,取模这样的操作符在不同的上下文语境里对应的语义动作也有所不同,而且这种差异还不

同于c++里的操作符重载在语言级别可见,而是要到更底层的汇编语言级别才可见,这多少就有

一些tricky,也容易诱使程序员犯错了。如果有机会我来设计一门语言,我想自己会尽量避免引

入这种tricky的东西的。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 32位无符号除法器是一种用于计算器、字信号处理器等电子工程中的字芯片。它可以执行32位无符号除法运算,无符号表示运算中不考虑正负号。在Verilog中实现32位无符号除法器需要以下步骤: 第一步是输入寄存器,并设置初始值。在该寄存器中输入需要进行除法运算的两个32位无符号B和A,其中被除A为32位,除B为32位。 第二步是进行除法操作,可以使用“非规范化除法法”或“高精度除法法”等算法。这里我们以“非规范化除法法”为例进行说明。首先将余寄存器初始化为被除A的值,然后除以B,如果余寄存器的值小于除B,则继续左移一位,将除B左移一位,然后再次减去除B。一直重复这个过程,直到余寄存器的值大于等于除B为止,此时将商寄存器的值左移一位,最后将商寄存器加上1。 第三步是输出商寄存器的结果。商寄存器存储的即为除法运算的结果,是32位无符号。 综上所述,我们可以在Verilog中实现32位无符号除法器,它能够进行32位无符号A/B的除法操作,并输出商寄存器的结果。这种除法器可以用于字计算器、字信号处理器等电子工程中的字芯片中。 ### 回答2: 32位无符号除法器是一种字电路设计,可以将32位无符号除以任意不为零的32位无符号。在Verilog语言中,可以使用模块化方法实现32位无符号除法器。 首先,需要定义输入输出端口,包括32位除dividend、32位除divisor和32位商quotient。接着,使用Verilog代码实现除法运算的算法,例如时间复杂度为O(n)的16位位移除法算法。在该算法中,先将除左移直至其最高位小于等于被除的最高位,然后将被除减去左移后的除,直到被除小于除,商的每一位由减法的次确定。 最后,需要注意除不能为零的情况,可以使用if语句判断并将商赋值为全零。此外,在实现中需要注意据类型的选择,整需要用无符号类型表示,如"reg [31:0] dividend"。 ### 回答3: 32位无符号除法器是一种能够将两个32位无符号相除的硬件电路。相对于软件实现,在硬件中实现除法运算可以获得更高的速度和性能,适用于需要快速且高效处理除法运算的场合。 在verilog语言中实现32位无符号除法器,需要写出divisor、dividend、quotient和remainder四个信号的代码,并通过实例化模块实现调用和传输据。在计算机底层结构中,实现方式主要是通过作差减法和移位右移的方式将除和被除逐渐逼近相等,并通过商和余的累计得出最终结果。 具体实现过程中,可以使用类似于Booth算法或者类似于龙皮递归算法的递归结构来进行除法计算。此外,在代码实现中还需要注意一些细节问题,如除为0的特殊情况、被除小于除的情况等,需要考虑如何解决或者报错提示。 总的来说,32位无符号除法器是一种实现除法运算的高效且可靠的方法。在硬件实现中可以使用verilog语言进行代码编写,并通过递归算法实现高效的除法运算。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值