例如,
1 2 3
| int result;
result = 125/100; |
要么
结果总会成为师的底线吗? 什么是定义的行为?
-
摘要:有符号整数除法截断为零。对于非负结果,这与floor(圆向-Infinity)相同。 (请注意,C89不保证这一点,请参阅答案。)
-
每个人都在说"截断到零"或"天花板"或"地板",就像代码正在故意决定使用哪种技术。如果代码可以说话,它会说"I just throw the dam fraction part in the trash and move on with life"
-
@ TimothyL.J.Stewart"代码"正在做出深思熟虑的决定。根据规范,整数除法意味着T(runcation) - 分区。因此,模数/余数运算符的实现方式与使用其他语言(如Python或Ruby)的方式不同。请参阅此文章,了解语言执行模运算符的不同方法列表,本文列出了编程语言决定执行div / modulo的至少五种常用方法。
-
@ 13steinj我正在口口相传,因为它正在变成一个"它向零的截断......不是它的底线......如果它的负面是它的上限......"有时技术性不会随着人类记忆传播到未来就像我们希望的那样,但直观地知道"分数部分被抛弃",你可以得出技术要点。技术性是一个沉重的负担,但直觉轻盈而清新如风,我将携带那些广泛的,必要时我会知道从哪里开始。就像那篇论文链接一样,谢谢。
-
我在这里回答的重点是欧几里德划分(整数除法和模运算符之间的相互作用)。
Will result always be the floor of the division? What is the defined behavior?
是,两个操作数的整数商。
6.5.5 Multiplicative operators
6 When integers are divided, the result of the / operator is the algebraic quotient with any
fractional part discarded.88) If the quotient a/b is representable, the expression
(a/b)*b + a%b shall equal a.
以及相应的脚注:
88) This is often called ‘‘truncation toward zero’’.
当然要注意的两点是:
3 The usual arithmetic conversions are performed on the operands.
和:
5 The result of the / operator is the
quotient from the division of the
first operand by the second; the
result of the % operator is the
remainder. In both operations, if the
value of the second operand is zero,
the behavior is undefined.
[注意:强调我的]
-
...当然,除非你将负数除以正数(或v.v.),在这种情况下,它将是最高限度。
-
它既不是地板也不是天花板,它是分数部分的截断,它在概念上是不同的!
-
@Will A:不。它被定义为截断为零。把它称之为其他东西只会增加混乱,所以请不要这样做。
-
至少从数学的角度来看,向零截断相当于"if> 0然后是其他上限。"我认为只是称它为截断比调用它/ floor是简单的,但要么是有效的。无论如何,威尔A的观点是有效的:Dirkgently的答案部分不正确,因为他表示OP对于结果是分区的结果是对的。
-
这种行为在C89中也是如此吗?我似乎记得模数没有严格定义。
-
@Philip Potter:我不认为它是在C89中定义的,它不符合1998 C ++标准。在那些中,当然必须满足(a / b) * b + a % b == a,并且a % b的绝对值必须小于a,但是没有指定a % b对于负a或b是否定的。
-
即使它被定义为截断为零,它仍然是非负情况下的最低操作和非正数情况下的上限操作。它们是等同的定义。更清楚地考虑哪个定义取决于您正在做什么。有时候在楼层和天花板方面考虑它会更方便,有时候在截断方面考虑它会更方便。
-
为什么会有这么多的赞成?它给出了错误的答案,然后引用与答案直接矛盾的标准部分。如果您可以根据楼层定义截断并不重要。问题的答案"将永远是分裂的底线吗?"毫无疑问是"不"
-
每个人都在说"截断到零"或"天花板"或"地板",就像代码正在故意决定使用哪种技术。如果代码可以说话,它会说"I just throw the dam fraction part in the trash and move on with life"
Dirkgently给出了C99中整数除法的优秀描述,但是您也应该知道在C89中,带有负操作数的整数除法具有实现定义的方向。
从ANSI C草案(3.3.5):
If either operand is negative, whether the result of the / operator is the largest integer less than the algebraic quotient or the smallest integer greater than the algebraic quotient is implementation-defined, as is the sign of the result of the % operator. If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a.
当你遇到C89编译器时,请注意负数。
这是一个有趣的事实,C99选择截断为零,因为这是FORTRAN如何做到的。请参阅comp.std.c上的此消息。
-
而C99草案N1256前言第5段提到reliable integer division作为一种新的语言特征。惊人的*-*。
-
截断是最常见的CPU硬件(例如x86)的行为,因此做出不同的选择会很疯狂。 首先出现的IDK,Fortran语义或硬件行为,但这些都是相同的并非巧合。
-
@PeterCordes:大多数常见的CPU硬件可以通过大多数常量进行浮动除法,而不是截断除法。 恕我直言,如果expr1 / expr2的两个实例以相同的方式组合相同的对象,同样对于expr2,那么expr1 / expr2和expr1 % expr2必须相互一致才会更好。 否则,截断与覆盖除法的选择是未指定的。 这样可以在不破坏太多兼容性的情况下实现更高效的代码生成(如果倾向于实现可以记录特定行为)
在结果为负的情况下,C截断为0而不是地板 - 我学习了这个解释为什么Python整数除法总是落在这里:为什么Python的整数分区Floors
-
我同意这个评论,想知道是否(负%pos)消极是否有用?在相关的说明中,我想知道在"unsignedvar> signedvar"的某些情况下所需的算术错误行为是否有用?我可以理解不要求总是正确行为的理由;我认为没有必要采取错误行为的理由。
-
+1对于为什么地板是整数除法的正确行为的一个很好的参考(与C的定义相反,它被破坏,几乎从不有用)。
-
正确而准确。 +1。
-
@supercat考虑:filtered = (k - 1) * filtered + value + carry; carry = filtered % factor; filtered /= factor,使用value的值更改进行迭代。它对具有时间常数k的一阶低通滤波器进行了一个很好的整数近似...但是如果除法是截断的并且carry得到负值,它只是对称的。分裂的两种行为都会不时地派上用场。
-
@hobbs:我不认为上面的代码在信号过零时会表现得很干净。如果div是一个内置除法运算符且factor是奇数,则filtered += (filter+(factor div 2)) div factor将为所有值INT_MAX-(factor div 2)产生干净且对称的行为。
-
@supercat它确实有效;该代码只是稍微从我在原子钟控制器中运行一段时间的东西中提炼出来的。
-
@hobbs:对于filtered carry和factor的任何给定值,将有"因子"值产生严格介于最小和最大可能输出之间的每个可能输出值,除非会有< x18>产生输出值为零的值。
是的,结果总是被截断为零。它将朝着最小的绝对值四舍五入。
对于无符号和非负有符号值,这与floor(向-Infinity舍入)相同。
-
截断,而不是地板。
-
@ dan04:yep floor只对正整数有效:)
Will result always be the floor of the division?
不会。结果会有所不同,但只有负值才会发生变化。
What is the defined behavior?
使整数分区朝向负无穷大,同时整数除法向零舍入(截断)
对于正值,它们是相同的
1 2
| int integerDivisionResultPositive = 125/100;//= 1
double flooringResultPositive = floor(125.0/100.0);//=1.0 |
对于负值,这是不同的
1 2
| int integerDivisionResultNegative = -125/100;//=-1
double flooringResultNegative = floor(-125.0/100.0);//=-2.0 |