关于两个负数的整数除法,C89的行为是什么:向上舍入,向下舍入或未定义?

时间:2018-04-27 18:50:57

标签: c c89 integer-division ansi-c rounding

例如,

如果我写

int var;
var=-8/-5;

根据运算符优先级,-8 / -5等于((-8)/( - 5))。 但C89是否有可能给出两个值,例如-8 / 5的情况,它可以给出-1或-2。 或者它将它视为两个正整数的划分?

问题在于参考K.N.King的书(C编程现代方法)

4 个答案:

答案 0 :(得分:6)

C89规定如果任一操作数为负数,则除法的结果可以向上或向下舍入。
C89-3.3.5:

  

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

例如在-8/5的情况下;输出可以是-1((-8)/5)或-2(-(8/5)) 在C99中,它保证被截断为0.

在你的情况下,两个操作数都是-ve和输出将是+ ve编号(在这种情况下为1或2)。

答案 1 :(得分:1)

C89允许实现对正负操作数的四种组合中的三种组合使用向上和向下舍入的任意组合(当两个操作数都为正时,它强制向下舍入)。当时,大多数平台以一种方式执行除法,这种方式会使操作数的所有组合截断比对某些组合使用任何其他舍入模式更有效,因此这些平台的C实现也是如此。这反过来导致C99强制要求这种特殊行为。

具有讽刺意味的是,许多平台现在执行划分的方式(处理除以常数作为乘法和移位操作),截断不再是处理非零余数的最有效方法,而是可以追溯到现在它被锁定在石头上。

答案 2 :(得分:1)

  

关于两个负数的划分,C89的行为是什么

商为1或2。

int var;
var=-8/-5;

C89允许对2个整数(至少有一个负数)进行除法,该整数对于更高或更低的整数结果具有非零余数。标准库提供了div()来计算编译器中的商和余数,而没有这种灵活性。

div_t     div( int x, int y );

此函数具有指定的“截断为零”,这是自C99以来/的行为。这允许便携式(如果有时效率稍低)C89代码。

答案 3 :(得分:0)

从K& R第二版(大约1988年)

  

二进制LEFT JOIN Reviews ON Contacts.id = Reviews.contact_id 运算符产生商,而/运算符产生   剩余部分,第一个操作数除以第二个;如果   第二个操作数是0,结果是未定义的,否则,它始终是   是的,%等于(a/b)*b + a%b。如果两个操作数都是   非负,那么余数是非负的,小于   除数;如果没有,它只保证绝对值   余数小于除数的绝对值。

例如,要计算a(根据C89规则),我们首先需要计算-8/-5。该规范允许余下的两个可能答案:-8%-5-3。两者都满足余数的绝对值小于除数的绝对值的要求,并且都满足2等于(a/b)*b + a%b的要求。

a

因此,允许(通过C89)除法的结果有两个不同的答案,因为(假设为负(-8/-5)*-5 + -3 = -8 ==> (-8/-5) = 1 since (1)*-5 + -3 = -8 (-8/-5)*-5 + 2 = -8 ==> (-8/-5) = 2 since (2)*-5 + 2 = -8 a),余数运算符b的结果可能是消极或积极的。这是在C99中修复的,它要求除法截断为0。

对于那些更具数学倾向的人,请注意

%

https://en.wikipedia.org/wiki/Congruence_relation