带符号整数的除法与余数

转载地址:http://blog.csdn.net/solstice/article/details/5139302

他的巧妙之处在于,用一个对称的 digits 数组搞定了负数转换的边界条件(二进制补码的正负整数表示范围不对称)。代码大致如下,经过改写:

 

[c-sharp] view plain copy
  1. const char* convert(char buf[], int value)  
  2. {  
  3.   static char digits[19] =  
  4.     { '9''8''7''6''5''4''3''2''1',  
  5.       '0''1''2''3''4''5''6''7''8''9' };  
  6.   static const char* zero = digits + 9;  // zero 指向 '0'  
  7.   // works for -2147483648 .. 2147483647  
  8.   int i = value;  
  9.   char* p = buf;  
  10.   do {  
  11.     int lsd = i % 10;  // lsd 可能小于 0  
  12.     i /= 10;           // 是向下取整还是向零取整?  
  13.     *p++ = zero[lsd];  // 下标可能为负  
  14.   } while (i != 0);  
  15.   if (value < 0) {  
  16.     *p++ = '-';  
  17.   }  
  18.   *p = '/0';  
  19.   std::reverse(buf, p);  
  20.   return p; // p - buf 即为整数长度  
  21. }  

 

 

这段简短的代码对 32-bit int 的全部取值都是正确的(从 -2147483648 到 2147483647)。可以视为 itoa() 的参考实现,面试的标准答案。

读到这份代码,我心中顿时升起一个疑虑:《C Traps and Pitfalls》第7.7节讲到,C 语言中的整数除法(/)和取模(%)运算在操作数为负的时候,结果是 implementation-defined。(网上能下载到的一份简略版也有相同的内容,http://www.literateprogramming.com/ctraps.pdf 第7.5节。)


也就是说,如果 m、d 都是整数,
int q = m / d;
int r = m % d;
那么C语言只保证 m == q*d + r。如果 m、d 当中有负数,那么 q 和 r 的正负号是由实现决定的。比如 (-13)/4 == (-3)或 (-13)/4 == (-4) 都是合法的。如果采用后一种实现,那么这段转换代码就错了(因为将有 (-1) % 10 == 9)。只有商向 0 取整,代码才能正常工作。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值