整数除法的行为是什么?

What is the behavior of integer division?

提问人:T.T.T. 提问时间:8/31/2010 最后编辑:LundinT.T.T. 更新时间:5/27/2021 访问量:522145

问:

例如

int result;

result = 125/100;

result = 43/100;

结果会永远是部门的底线吗?定义的行为是什么?

C 数学 C99 C89 整数除法

评论

9赞 Peter Cordes 11/7/2017
摘要:有符号整数除法截断为零。对于非负结果,这与下限相同(向 -Infinity 舍入)。(请注意,C89 不能保证这一点,请参阅答案。
58赞 Timothy L.J. Stewart 10/8/2018
每个人都在说“截断到零”或“天花板”或“下限”,就像代码在深思熟虑地决定使用哪种技术一样。如果代码会说话,它会说"I just throw the dam fraction part in the trash and move on with life"
7赞 13steinj 10/24/2018
@TimothyL.J.Stewart:“代码”正在做出深思熟虑的决定。根据规范,整数除法是指 T(runcation)除法。正因为如此,模/余数运算符的实现方式与另一种语言(例如 Python 或 Ruby)不同。请参阅本文,了解语言执行模运算符的不同方式,本文列出了编程语言决定执行 div/modulo 的至少五种常见方式。
7赞 Timothy L.J. Stewart 10/24/2018
@13steinj,我通俗地说,根据评论,它变成了“它正在向零截断......不,是地板......不,如果它是负面的,它的上限......”有时,技术性不会像我们希望的那样通过人类记忆传播到未来,但凭直觉知道“分数部分被扔掉了”,你就可以得出技术要点。技术细节是一个沉重的负担,但直觉是轻盈的,像风一样令人耳目一新,我会把它们带到很远很远的地方,必要时我会知道从哪里开始。喜欢你链接的那篇论文,谢谢。
0赞 Picaud Vincent 5/19/2019
在这里的回答是强调欧几里得除法(整数除法和模运算符之间的相互作用)。

答:

38赞 Leonid 8/31/2010 #1

是的,结果总是被截断为零。它将向最小的绝对值四舍五入。

-5 / 2 = -2
 5 / 2 =  2

对于无符号和非负有符号值,这与 floor 相同(向 -Infinity 舍入)。

评论

9赞 Leonid 8/31/2010
@dan04:是的,下限仅对正整数有效:)
234赞 dirkgently 8/31/2010 #2

结果会永远是部门的底线吗?定义的行为是什么?

差一点。它向 0 四舍五入,而不是地板。

6.5.5 乘法运算符

6 当整数被除以时,/ 运算符的结果是代数商与任何 丢弃部分。88) 如果商 a/b 是可表示的,则表达式 (a/b)*b + a%b 等于 a。

以及相应的脚注:

  1. 这通常被称为“向零截断”。

当然有两点需要注意:

3 通常的算术转换是在操作数上执行的。

和:

5 / 运算符的结果是 商来自 除法 第一个操作数由第二个操作数;这 % 运算符的结果是 剩余。在这两个操作中,如果 第二个操作数的值为零, 行为未定义。

[注:强调我的]

评论

27赞 Will A 8/31/2010
...当然,除非你把一个负数除以一个正数(或V.V.),在这种情况下,这将是上限。
86赞 lornova 8/31/2010
它既不是地板也不是天花板,它是小数部分的截断,它在概念上是不同的!
44赞 Martin York 8/31/2010
@Will答:没有。它被定义为向零截断。称它为其他任何东西只会增加混乱,所以请不要这样做。
50赞 Brian 8/31/2010
至少从数学的角度来看,向零截断等同于“如果> 0,则为下限上限”。我认为仅仅称其为截断比称其为地板/天花板更简单,但两者都是有效的。无论如何,Will A 的观点是有道理的:Dirkgently 的回答部分不正确,因为他说 OP 关于结果是部门下限是正确的。
9赞 David Thornley 8/31/2010
@Philip Potter:我不认为它是在 C89 中定义的,也不是在 1998 年的 C++ 标准中定义的。在这些中,当然必须满足,并且 的绝对值必须小于 ,但是否为负数或未指定。(a / b) * b + a % b == aa % baa % bab
27赞 Gareth Williams 8/31/2010 #3

如果结果为负数,则 C 会截断为 0 而不是 flooring - 我在这里学习了关于为什么 Python 整数除法总是 floors 的读物: 为什么 Python 的整数除法 floors

评论

4赞 supercat 8/31/2010
我同意这样的评论,想知道(负 % pos)变为负值是否有用?与此相关的是,我想知道在某些情况下“unsignedvar > signedvar”所需的算术错误行为是否有用?我能理解不要求始终正确的行为的基本原理;我认为没有理由要求错误的行为。
8赞 R.. GitHub STOP HELPING ICE 8/31/2010
+1 是一个很好的参考,说明为什么地板是整数除法的正确行为(与 C 的定义相反,C 的定义是破碎的,几乎从来都没有用)。
0赞 hobbs 12/21/2017
@supercat 考虑: ,使用不断变化的值进行迭代。它对具有时间常数的一阶低通滤波器进行了很好的整数近似......但只有当除法被截断并得到负值时,它才是对称的。这两种划分行为都会不时派上用场。filtered = (k - 1) * filtered + value + carry; carry = filtered % factor; filtered /= factorvaluekcarry
1赞 supercat 12/22/2017
@hobbs:我不认为上面的代码在信号过零时会表现得很干净。如果是地板除法运算符并且是奇数,则将对所有值产生干净且对称的行为,直到 。divfactorfiltered += (filter+(factor div 2)) div factorINT_MAX-(factor div 2)
0赞 hobbs 1/17/2018
@supercat它确实有效;该代码只是从我在原子钟控制器中运行了一段时间的东西中略微提炼出来的。
55赞 schot 8/31/2010 #4

Dirkgently对C99中的整数除法进行了很好的描述,但您还应该知道,在C89中,具有负操作数的整数除法具有实现定义的方向。

来自 ANSI C 草案 (3.3.5):

如果任一操作数为负数,则 / 运算符的结果是小于代数商的最大整数还是大于代数商的最小整数,以及 % 运算符结果的符号都是由实现定义的。如果商 a/b 是可表示的,则表达式 (a/b)*b + a%b 应等于 a。

因此,当您遇到 C89 编译器时,请注意负数。

一个有趣的事实是,C99 选择将截断趋向零,因为 FORTRAN 就是这样做的。在 comp.std.c 上查看此消息

评论

4赞 Ciro Santilli OurBigBook.com 9/11/2016
而 C99 草案 N1256 前言第 5 段提到作为新的语言功能。了不起。reliable integer division*-*
1赞 Peter Cordes 11/7/2017
截断是最常见的 CPU 硬件(例如 x86)的行为方式,因此做出不同的选择是疯狂的。首先出现的 IDK、Fortran 语义或硬件行为,但这些也并非巧合。
3赞 supercat 7/1/2018
@PeterCordes:大多数常见的 CPU 硬件可以比截断除法更快地按大多数常数进行地板除法。恕我直言,当两个实例以相同的方式组合相同的对象时,标准最好这样说并且必须彼此一致,同样对于 ,但截断与地板分割的选择在其他方面是未指定的。这将允许更高效的代码生成,而不会破坏太多兼容性(如果愿意,实现可以记录特定行为)expr1 / expr2expr1 % expr2expr1expr2
13赞 Mohamed El-Nakeep 2/6/2015 #5

结果会永远是部门的底线吗?

不。结果各不相同,但变化仅发生在负值上。

定义的行为是什么?

为了清楚起见,地板向负无穷大舍入,而整数除法向零舍入(截断)

对于正值,它们是相同的

int integerDivisionResultPositive= 125/100;//= 1
double flooringResultPositive= floor(125.0/100.0);//=1.0

对于负值,这是不同的

int integerDivisionResultNegative= -125/100;//=-1
double flooringResultNegative= floor(-125.0/100.0);//=-2.0
4赞 adi1ya 4/5/2020 #6

我知道人们已经回答了你的问题,但用通俗的话说:

5 / 2 = 2由于 5 和 2 都是整数,因此整数除法总是截断小数点

5.0 / 2 or 5 / 2.0 or 5.0 /2.0 = 2.5这里 5 或 2 或两者都有小数,因此您将得到的商将是十进制。