【问题标题】:int division rounding library?int 除法舍入库?
【发布时间】:2013-01-21 03:45:17
【问题描述】:

有谁知道一个开源 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 编写一个,发布它,并在此处的答案中链接到它。

【问题讨论】:

  • 在 C++11 中有一些,在 Boost 中有更多。不过,我不记得那些范围。
  • 可能没有库,因为您可以通过添加 0.5 并强制转换为 int 来获得正常的舍入行为
  • @technosaurus, std::round 也这样做。
  • 你为什么要这个?内联并不难:round = (int)(+0.5), round_down = (int)number 等等。
  • 我相信&lt;math.h&gt; 上的大部分功能都有,比如ceil()floor()

标签: c++ c math int integer-division


【解决方案1】:

所以,我写了一些东西。该实现通常是丑陋的模板和按位代码,但效果很好。用法:

divide(dividend, divisor, rounding_strategy<...>())

其中rounding_strategy&lt;round_up, negative_mirrors_positive&gt; 是一个示例策略;请参阅我的问题或源代码中的变体列表。 https://github.com/idupree/Lasercake/blob/ee2ce96d33cad10d376c6c5feb34805ab44862ac/data_structures/numbers.hpp#L80

仅依赖于 C++11 [*],单元测试(使用 Boost Test 框架)从 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() 或if(..){throw ..} 或已删除。假设您对那里的其他内容不感兴趣,您可以忽略并删除文件的其余部分。)

每个 divide_impl 的代码都可以通过用例如替换每个 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.phphttp://en.cppreference.com/w/cpp/numeric/math/div

【讨论】:

    猜你喜欢
    • 2019-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 2013-04-23
    • 1970-01-01
    • 2019-03-02
    • 1970-01-01
    相关资源
    最近更新 更多