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
进行整数除法。如果 a
或 b
为负数,则结果取决于编译器(在 C99 之前的版本中,舍入可以趋向零或负无穷大;在 C99+ 中,舍入趋向 0)。结果的类型为int
。 floor(a/b)
执行相同的除法,将结果转换为双精度,丢弃(不存在的)小数部分,并将结果作为双精度返回。
【讨论】:
在 C 中整数除法执行向零截断。从 C99 开始就是这样,在实现定义之前。 啊,错过了C
标签。不过,很明显我的答案是关于 C++。 <g>
@Mysticial 的重点是floor
在这种情况下不会四舍五入,因为a / b
执行整数除法,然后然后 将其传递给floor
。跨度>
-4 / 3 == -1
而floor(-4 / 3) == -2
【参考方案2】:
floor
返回一个double
而a / b
其中a
和b
都是整数,产生一个整数值。
使用正确的转换,值是相同的。
如果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整数除法和下限的主要内容,如果未能解决你的问题,请参考以下文章