有没有人知道一个开源C或C ++库,其函数实现了人们可能想要的每个整数除法模式?可能的行为(积极的结果):
round_down, round_up,
round_to_nearest_with_ties_rounding_up,
round_to_nearest_with_ties_rounding_down,
round_to_nearest_with_ties_rounding_to_even,
round_to_nearest_with_ties_rounding_to_odd
每个(除了圆形到偶数和圆形到奇数)有两个变体
// (round relative to 0; -divide(-x, y) == divide(x, y))
negative_mirrors_positive,
// (round relative to -Infinity; divide(x + C*y, y) == divide(x, y) + C)
negative_continuous_with_positive
我知道如何写它,但肯定有人已经这样做了吗?
作为一个例子,如果我们假设(通常并且在C ++ 11中强制要求)内置有符号整数除法向零舍入,并且内置模数与此一致,那么
int divide_rounding_up_with_negative_mirroring_positive(int dividend, int divisor) {
// div+mod is often a single machine instruction.
const int quotient = dividend / divisor;
const int remainder = dividend % divisor;
// this ?:'s condition equals whether quotient is positive,
// but we compute it without depending on quotient for speed
// (instruction-level parallelism with the divide).
const int adjustment = (((dividend < 0) == (divisor < 0)) ? 1 : -1);
if(remainder != 0) {
return quotient + adjustment;
}
else {
return quotient;
}
}
奖励积分:适用于多种参数类型;快速;任选返回模数;不要为任何参数值溢出(除了除以零和MIN_INT / -1,当然)。
如果我找不到这样的库,我会在C ++ 11中编写一个,发布它,然后在答案中链接到它。
答案 0 :(得分:1)
所以,我写了一些东西。实现通常是丑陋的模板和按位代码,但它运行良好。用法:
divide(dividend, divisor, rounding_strategy<...>())
其中rounding_strategy<round_up, negative_mirrors_positive>
是一个示例策略;请参阅我的问题或源代码中的变体列表。 https://github.com/idupree/Lasercake/blob/ee2ce96d33cad10d376c6c5feb34805ab44862ac/data_structures/numbers.hpp#L80
仅依赖于C ++ 11 [*],单元测试(使用Boost测试框架)从https://github.com/idupree/Lasercake/blob/ee2ce96d33cad10d376c6c5feb34805ab44862ac/tests/misc_utils_tests.cpp#L38开始
它是多态的,速度不错,并且不会溢出,但目前不会返回模数。
[*](和boost :: make_signed和boost :: enable_if_c一样,用std :: make_signed和std :: enable_if替换它们很简单,在我们的caller_error_if()上可以用assert()代替如果(..){throw ..}或删除。你可以忽略并删除文件的其余部分,假设你对那里的其他东西不感兴趣。)
每个divide_impl的代码可以通过用例如T替换每个T来适应C。 int和T(CONSTANT)与CONSTANT。在round_to_nearest_ *变体的情况下,您要么想要将舍入类型作为运行时参数,要么创建代码的六个副本(一个代码用于它处理的每个不同的舍入变量)。代码依赖于'/'舍入为零,这是常见的,也由C11(标准草案N1570 6.5.5.6)以及C ++ 11指定。对于C89 / C ++ 98兼容性,它可以使用stdlib.h div()/ ldiv(),它们保证向零舍入(参见http://www.linuxmanpages.com/man3/div.3.php,http://en.cppreference.com/w/cpp/numeric/math/div)