C整数除法和向下取整

23
在C语言中,当a和b为整数时,整数除法a/b和floor(a/b)有区别吗?更具体地说,在这两个过程中会发生什么?

1
可能是整数除法的行为是什么?的重复问题。 - phuclv
4个回答

24

a/b 是整数除法。如果 ab 中存在负数,结果将取决于编译器(在 C99 之前,舍入可能朝零或负无穷方向;在 C99+ 中,向零舍入)。结果的类型为 intfloor(a/b) 执行相同的除法运算,将结果转换为双精度浮点数,舍弃(不存在的)小数部分,并将结果作为双精度浮点数返回。


7
在C语言中,整数除法向零取整。这是自C99以来的规定,但在此之前是由具体实现定义的。 - ouah
1
啊,我错过了 C 标签。但是,很明显我的回答是关于 C++ 的。 <g> - Pete Becker
@Mysticial 的意思是,这里的 floor 并没有四舍五入任何东西,因为 a / b 执行整数除法,然后将其传递给 floor - obataku
-4 / 3 == -1 while floor(-4 / 3) == -2 - Geoff Armstrong

9

floor返回一个double,而a/b,其中ab都是整数,则产生一个整数值。

通过正确的转换,值是相同的。

如果C语言中存在typeof运算符(实际上不存在),我们会有:

(typeof (a /b)) floor(a / b) == a / b

编辑:现在问题是:以下两者是否有差别:

(double) (a / b)

并且

floor(a / (double) b)

答案是肯定的。对于负值,结果有所不同。

5

将整数转换为浮点数时可能会丢失信息,对于 int 和 double 类型而言不太可能发生,但稍作修改:

#include <stdio.h>
#include <math.h>

int main(void)
{
    unsigned long long a = 9000000000000000003;
    unsigned long long b = 3;
    printf("a/b = %llu\n", a/b);
    printf("floor(a/b) = %f\n", floor(a/b));
    return 0;
}

结果:

a/b = 3000000000000000001
floor(a/b) = 3000000000000000000.000000

3
一个双精度浮点数可以准确地存储所有32位整数值。你总是可以使用双精度浮点数代替整数类型。不仅不太可能失去精度,而且是不可能的。你的例子是正确的,但会误导那些还不理解这个问题的人。 - maxy

3
一般情况下,假设整数在整数和浮点类型中都可表示,它们之间没有区别,但证明并不显然。问题在于,在浮点数中,除法a/b会发生舍入,因此floor函数不适用于精确有理值,而是适用于近似值。我写过一篇关于这个问题的论文:https://www.vinc17.net/research/publi.html#Lef2005b 简而言之,我得出的结论是,如果a-b在浮点系统中可以被精确表示,则浮点数a和b(具有整数值)的floor(a/b)将得到与整数除法a/b相同的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接