【问题标题】:c++ rounding of numbers away from zeroc ++将数字从零四舍五入
【发布时间】:2009-08-25 07:11:49
【问题描述】:

您好,我想在 C++ 中像这样(远离零)舍入双数:

  4.2 ---->   5
  5.7 ---->   6
 -7.8 ---->  -8
-34.2 ----> -35

这样做的有效方法是什么?

【问题讨论】:

  • 从(原始)标题“C++ 双舍入”,我以为你的意思是把一个数字舍入两次,只是为了确定 :-)

标签: c++ double rounding


【解决方案1】:
inline double myround(double x)
{
  return x < 0 ? floor(x) : ceil(x);
}

正如the article Huppie cites 中所述,最好将其表示为适用于所有浮点类型的模板

http://en.cppreference.com/w/cpp/numeric/math/floorhttp://en.cppreference.com/w/cpp/numeric/math/floor

或者,感谢 Pax,一个非功能版本:

x = (x < 0) ? floor(x) : ceil(x);

【讨论】:

  • 很好,@Ruben,添加了一个非函数变体并给了你一票。希望你不介意(编辑,也就是说,显然你不介意投票)。
  • 自己等待 3k - 添加到内联说明符中 - 我倾向于尝试找到一个好名称并将其粘贴到 util lib 中,可能作为所有浮点数的模板 - 它不会花费任何效率,并允许您快速隔离或更改它的所有用法
【解决方案2】:

CPlusPlus.com 上有一篇关于类似问题的好文章。您的问题的简单解决方案应该是这样的:

double customRound( double value ) const {
   return value < 0 ? floor( value ) : ceil( value );
}

一个更好的解决方案是文章中提到的,它使用了一个模板:

//--------------------------------------------------------------------------
// symmetric round up
// Bias: away from zero
template <typename FloatType>
FloatType ceil0( const FloatType& value )
{
   FloatType result = std::ceil( std::fabs( value ) );
   return (value < 0.0) ? -result : result;
}

【讨论】:

  • 为什么不叫 customFloor - 它既不是:P
  • 我在引用的文章中看到它的含义是 template <typename floattype> FloatType ceil0( const FloatType&amp; value ) { FloatType result = std::ceil( std::fabs( value ) );返回(值 有趣的文章,+1</typename>
  • @Ruben Bartelink:'Round' 应该更好:)...顺便说一句...你有一些忍者打字技巧 ;-)
  • 键入或剪切和粘贴 :P 我的键入实际上很尴尬 - 请参阅 blog.jpboodhoo.com/…(不,还没有这样做)。我认为即使是“Round”也有点通用,并且在 stdlib 中具有普遍理解的含义 - 点是他想要的非常具体的算法,使用 floor、ceil 或 round 都不能准确地传达这一点。
  • 因为无论如何都要分支,所以绝对值有些多余:return (value &lt; 0.0) ? -std::ceil(-value) : std::ceil(value)
【解决方案3】:

Ruben Bartelinkx &lt; 0 ? floor(x) : ceil(x); 方法很好。但是考虑一下x = -0.0x = NaN 的特殊情况会发生什么。

与其让myround(-0.0) 可能返回+0.01 并让myround(NaN) 返回带有NaN 的更改有效负载,请考虑以下内容。

myround_alt(-0.0) 返回-0.0

myround_alt(NaN)更有可能返回不变的有效载荷 NaN。非数字的东西很棘手,也没有很好的定义。 IAC,是myround_alt(-0.0) --> -0.0 我要找的。​​p>

inline double myround_alt(double x) {
  if (x > 0) return ceil(x);
  if (x < 0) return floor(x);
  return x;
}

1IEC 60559 floating-point arithmetic 指定ceil(±0) 返回±0,因此严格遵循该规范的实现不需要这种方法。然而,许多 C 浮点实现不遵循这一点(C 不需要它)或在这种情况下失败。

【讨论】:

    【解决方案4】:

    试试

     double rounded = _copysign(ceil(abs(x)), x);
    

    【讨论】:

    • 但是如果我的值是-3.4,ceil会返回更大的整数值,我加上0.5会是-2.9,ceil会返回-2我想要一些东西-4
    • ceil(x + 0.5) for x=5.7 会产生 7 而不是 6,不是吗?
    • 它仍然不适用于指定的负数,请参阅我链接的地方的示例
    • 现在它不再那么高效了,即使它使用了一个有趣的技巧——_copysign 来自哪里?
    • 这是一个很好的技术:智能编译器/运行时应该允许abs 将符号位与 0 进行位与运算,执行 ceil(祈祷快点完成),然后重新签名通过将其符号位与原始符号位进行位或运算得到结果。 无条件 = 无分支错误预测 = 无管道刷新 = 非常快。
    猜你喜欢
    • 2017-09-02
    • 2015-11-12
    • 1970-01-01
    • 1970-01-01
    • 2011-07-16
    • 2020-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多