C整数除法和下限

Posted

技术标签:

【中文标题】C整数除法和下限【英文标题】:C integer division and floor 【发布时间】:2012-09-02 22:22:01 【问题描述】:

在 C 中,整数除法 a/b 和 floor(a/b) 之间是否有区别,其中 a 和 b 都是整数? 更具体地说,在这两个过程中会发生什么?

【问题讨论】:

What is the behavior of integer division?的可能重复 【参考方案1】:

a/b 进行整数除法。如果 ab 为负数,则结果取决于编译器(在 C99 之前的版本中,舍入可以趋向零或负无穷大;在 C99+ 中,舍入趋向 0)。结果的类型为intfloor(a/b) 执行相同的除法,将结果转换为双精度,丢弃(不存在的)小数部分,并将结果作为双精度返回。

【讨论】:

在 C 中整数除法执行向零截断。从 C99 开始就是这样,在实现定义之前。 啊,错过了C 标签。不过,很明显我的答案是关于 C++。 <g> @Mysticial 的重点是floor 在这种情况下不会四舍五入,因为a / b 执行整数除法,然后然后 将其传递给floor。跨度> -4 / 3 == -1floor(-4 / 3) == -2【参考方案2】:

floor 返回一个doublea / b 其中ab 都是整数,产生一个整数值。

使用正确的转换,值是相同的。

如果typeof 运算符存在于 C 中(它不存在),我们将:

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

编辑:现在如果问题是:有什么区别:

(double) (a / b)

floor(a / (double) b)

答案是肯定的。负值的结果不同。

【讨论】:

【参考方案3】:

从整数转换为浮点可能会丢失信息。不太可能与 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

【讨论】:

double 可以精确存储所有 32 位整数值。您始终可以使用 double 而不是 int。不仅不太可能失去精度,而且是不可能的。您的示例是正确的,但会误导尚未了解问题的人。【参考方案4】:

一般来说,假设整数在整数和浮点类型中都可以表示,没有区别,但证明并不明显。问题在于,在浮点数中,除法 a/b 中会发生舍入,因此底函数不适用于精确的有理值,而是适用于近似值。我写了一篇关于这个主题的论文:https://www.vinc17.net/research/publi.html#Lef2005b

简而言之,我得到的结果是,如果 a - b 在浮点系统中是完全可表示的,那么 floor(a/b),其中 a 和 b 是浮点数(具有整数值) , 与整数除法 a/b 的结果相同。

【讨论】:

以上是关于C整数除法和下限的主要内容,如果未能解决你的问题,请参考以下文章

连续截断整数除法可以用乘法代替吗?

如何解决使用 Z3 产生整数结果的整数除法?

求助:C语言大整数相除

Python中整数运算除法,输出带浮点数

整数除法的解释——C代码

用辗转相除法求两个整数的最大公约数