我想要一些C ++中的东西,它允许我使用指定的舍入行为进行有效的整数除法,如下所示:
div_down(-4,3) ==> -2
div_up(4,3) ==> 2
div_to_zero(-4,3) ==> -1
div_to_nearest(5,3) ==> 2
我希望它能够在编译时检测目标机器的行为并生成适当的最佳实现。类似于模数的东西也会很好,在编译时抽象出负操作数的未定义行为。
这是否存在?
如果没有,有什么好办法呢?我可以想到几种可能的方法:
答案 0 :(得分:5)
这是我到目前为止所得到的,前提条件d>它们似乎都有效,但它们可以简化吗?
int div_down(int n, int d) {
if (n < 0) {
return -((d - n - 1) / d);
} else {
return n / d;
}
}
int div_up(int n, int d) {
if (n < 0) {
return -(-n / d);
} else {
return (n + d - 1) / d;
}
}
int div_to_zero(int n, int d) {
return n / d;
}
int div_to_nearest(int n, int d) {
if (n < 0) {
return (n - d/2 + 1) / d;
} else {
return (n + d/2) / d;
}
}
答案 1 :(得分:4)
一个旧帖子,但它就在这里。请接受&amp;如果你喜欢,请评价它。
int div_to_zero(int n, int d) { return n / d; }
//as per C++11 standard note 80
int div_up(int n, int d) {
return n / d + (((n < 0) ^ (d > 0)) && (n % d));
} //i.e. +1 iff (not exact int && positive result)
int div_down(int n, int d) {
return n / d - (((n > 0) ^ (d > 0)) && (n % d));
} //i.e. +1 iff (not exact int && negative result)
int div_to_nearest(int n, int d) {
return (2*n - d + 2*(true&&(n<0^d>0))*d) / (2*d);
} //i.e. +-0.5 as per pre-rounding result sign, then div_to-zero
//it however rounds numbers like +/- 3.5 towards 0 and not even.
注意:大多数现代编译器将使用单个除法运算来同时使用n / d和n%d。因此,性能方面最好的是减少内存移动。
答案 2 :(得分:1)
C ++ 11的最后一个草案,n3242 几乎与实际的C ++ 11标准相同,在5.6分4(第118页)中说明了这一点:
对于积分操作数,/运算符产生代数商 丢弃任何小数部分; (见注80)
注意80个州(请注意,注释是非规范性的):
80)这通常被称为零截断。
为了完整起见,Point 4继续说明:
如果商a / b在结果类型中是可表示的, (a / b)* b + a%b等于a。
可以证明a%b
的符号与a
的符号相同(非零时)。
注意:实际的C ++ 11标准不合法在线。但是,草案是。幸运的是,最后草案(N3242)与实际标准之间的差异很小。请参阅this answer。
注意:我不确定哪些编译器符合C ++ 11标准。
所以div_to_zero()
是常规的/
部门。
对于其他功能,我担心你必须测试a
和b
的迹象并进行相应的调整。有时,可能需要额外检查a%b
是否等于零。因此,我们在这里查看每个函数的12个测试用例(3个符号或者是z的符号,b符号的时间为2,无论a%b
是否等于0,时间为2)。
现在对我来说太过分了,所以也许别人会跳进去提供正确答案。
我知道我没有回答你的问题,但上面的信息似乎很有价值,而且太大而无法发表评论。