C语言负数的除法和求余运算
假定我们让 a 除以 b,商为 q,余数为 r: q = a / b;
r = a % b;
这里,不妨假定 b 大于 0。
我们希望 a、b、q、r 之间维持怎样的关系呢?
1.最重的一点,我们希望 q * b + r == a,因为这是定义余数的关系。
2.如果我们改变 a 的正负号,我们希望这会改变 q 的符号,但这不会改变 q 的绝对值。
3.当 b>0 时,我们希望保证 r >= 0 且 r < b。例如,如果余数用于哈希表的索引,确保 它是一个有效的索引值很重 。
这三条性质是我们认为整数除法和余数操作所应该具备的。很不幸的是,它们不可能同时成立。
考虑一个简单的例子:3/2,商为 1,余数也为 1。此时,第 1 条性质得到了满足。(-3)/2 的值应该是多少呢?如果 满足第 2 条性质,答案应该是-1,但如果是这样,余数就必定是-1,这样第 3 条性质就无法满足了。如果我们首先满足第 3 条性质,即余数是 1,这种情况下根据第 1 条性质则商是-2,那么第 2 条性质又无法满足了。
因此,C 语言或者其他语言在实现整数除法截断运算时,必须放弃上述三条原则中的至 少一条。大多数程序设计语言选择了放弃第 3 条,而改为 求余数与被除数的正负号相同。 这样,性质 1 和性质 2 就可以得到满足。大多数 C 编译器在实践中也都是这样做的。
然而,C 语言的定义只保证了性质 1,以及当 a>=0 且 b>0 时,保证|r| < |b|以及 r>=0。 后面部分的保证与性质 2 或者性质 3 比较起来,限制性 弱得多。
C 语言的定义虽然有时候会带来不需 的灵活性,但大多数时候,只要编程者清楚地知道要做什么、该做什么,这个定义对让整数除法运算满足其需要来说还是够用了的。例如,
假定我们有一个数 n,它代表标识符中的字符经过某种函数运算后的结果,我们希望通过除 法运算得到哈希表的条目 h,满足 0<=h<HASHSIZE。又如果己知 n 恒为非负,那么我们只需要像下面一样简单地写:
h=n%HASHSIZE:
然而,如果 n 有可能为负数,而此时 h 也有可能为负,那么这样做就不一定总是合适 的了。不过,我们己知 h>-HASHSIZE,因此我们可以这样写:
h = n % HASHSIZE;
if(n < 0)
h += HASHSIZE;
更好的做法是,程序在设计时就应该避免 n 的值为负这样的情形,并且声明 n 为无符号数。
测试代码:
#include <stdio.h>
main()
{
int a=-, b=;
int q,r;
q = a / b;
r = a % b;
printf("q=%d, r=%d\n", q, r);
}
C语言负数的除法和求余运算的更多相关文章
- Swift 求余运算
求余运算 求余运算(a % b)是计算b的多少倍刚刚好可以容入a,返回多出来的那部分(余数). 注意:求余运算(%)在其他语言也叫取模运算.然而严格说来,我们看该运算符对负数的操作结果,"求 ...
- java 整除(/) 求余(%) 运算
1. java 整除(/) 求余(%) 运算 1.求余 System.out.println(11%2); //顾名思义就是11除2的余数-->1 System.out. ...
- PHP:第一章——按位运算和求余运算(判断奇偶数)
<?php //按位运算:与1按位运算等于0,输出偶数.如果等于1,输出奇数 //输出偶数: for($i=0;$i<10;$i++){ if(($i & 1)==0){ echo ...
- 051-PHP求余运算
<?php $x=10%5; //进行求余运算 $y=10%3; //进行求余运算 $z=10%6; //进行求余运算 echo $x; //输出变量x的值 echo $y; //输出变量y的值 ...
- 和求余运算巧妙结合的jns指令
.text:004A78B1 and eax, 80000001h.text:004A78B6 jns short loc_4A78BD.text:004A78B8 dec eax.text:00 ...
- Sicily1020-大数求余算法及优化
Github最终优化代码: https://github.com/laiy/Datastructure-Algorithm/blob/master/sicily/1020.c 题目如下: 1020. ...
- Verilog求余
在实现三角函数时,考虑到函数的周期性,综量(自变量)需对周期做求余运算. 假设函数周期为T = 2^N,那么求余运算就是直接取该数的低N位,即: 以M位正数为例(符号位为0),reg [M-1:0] ...
- Java求余%引发的一连串故事
C1 RCE对%的处理 HotSpot VM的C1有个RCE(Range Check Elimination,范围检查消除)优化,所谓范围检查消除,就是为了正确的抛出数组越界异常,虚拟机需要在数组访问 ...
- java学习--高效的除模取余运算(n-1)&hash
没有测试过使用取余运算符和位运算符都做同一件事时的时间效率! 取余运算符% 如3除以2取余数 a = a%; 结果为1 上面是传统的方式进行求余运算. 需要先将10进制转成2进制到内存中进行计算,然后 ...
随机推荐
- iOS开发笔记:编译时出现的错误和解决办法
1."std::ios_base::Init::~Init()", referenced from 出现这样的编译问题,是需要再加进libstdc++.dylib和libstdc+ ...
- C# - ADO.Net 调用存储过程
------------------------存储过程调用,创建DataSet:----------------------//数据库连接字符串string connStr = @"Dat ...
- 20151217--Ajax的一点补充
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- JAVA 可视化分析工具 第12节
JAVA 可视化分析工具 第12节 经过前几章对堆内存以及垃圾收集机制的学习,相信小伙伴们已经建立了一套比较完整的理论体系!那么这章我们就根据已有的理论知识,通过可视化工具来实践一番. 我们今天要讲 ...
- SSH框架整合 日志处理Spring结合 log4j、slf4j
1. 加入log4j和slf4j的jar包 2. web.xml: <context-param> <!--log4j配置地址 --> <param-name>lo ...
- EC读书笔记系列之13:条款25 考虑写出一个不抛异常的swap函数
记住: ★当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定其不抛出异常 ★若你提供一个member swap,也该提供一个non-member swap来调用前者.对于cla ...
- lightoj 1038 Race to 1 Again
题意:给一个数,用这个数的因数除以这个数,直到为1时,求除的次数的期望. 设一个数的约数有M个,E[n] = (E[a[1]]+1)/M+(E[a[2]]+1)/M+...+(E[a[M]]+1)/M ...
- PHP比较全的友好的时间显示,比如‘刚刚’,'几秒前'等
分享一个php友好的比较完成的时间格式化函数,包括‘刚刚’,'几秒之前',‘几分钟前’,'几小时前',几天前,几周前,几个月前等.调用方式很简单,是从ThinkSNS 里面拿出来的. /** * 友好 ...
- 图片压缩上传 Android
图片压缩的话 想保持 图像清晰度,但是又想保持图片的大小在100k左右. 同时的话又不想自己写那些压缩的代码的话.那你就找对地方了. 提供一个思路. 先读取你的文件,然后读到bitmap里面进行尺寸裁 ...
- jq方法
DOM属性-获取和设置页面元素的DOM属性 .addClass()..attr()..prop()..hasClass()..html()..removeAttr()..removeClass().. ...