Ceil功能:我们如何自己实现?

时间:2011-12-04 18:05:02

标签: c++ ceil

我知道C ++为我们提供了ceil函数。对于练习,我想知道如何在C ++中实现ceil函数。该方法的签名是 public static int ceil(float num)

请提供一些见解。

我想到了一个简单的方法:将num转换为字符串,找到小数点的索引,检查小数部分是否大于0.如果是,则返回num + 1,否则返回num。但我想避免使用字符串转换

9 个答案:

答案 0 :(得分:25)

您可以拆分IEEE754浮点数的成分并自行实现逻辑:

#include <cstring>

float my_ceil(float f)
{
    unsigned input;
    memcpy(&input, &f, 4);
    int exponent = ((input >> 23) & 255) - 127;
    if (exponent < 0) return (f > 0);
    // small numbers get rounded to 0 or 1, depending on their sign

    int fractional_bits = 23 - exponent;
    if (fractional_bits <= 0) return f;
    // numbers without fractional bits are mapped to themselves

    unsigned integral_mask = 0xffffffff << fractional_bits;
    unsigned output = input & integral_mask;
    // round the number down by masking out the fractional bits

    memcpy(&f, &output, 4);
    if (f > 0 && output != input) ++f;
    // positive numbers need to be rounded up, not down

    return f;
}

(在此插入通常的“非便携式”免责声明。)

答案 1 :(得分:9)

以下是正数的天真实现(这使用了向(int)转换为零的事实:

int ceil(float num) {
    int inum = (int)num;
    if (num == (float)inum) {
        return inum;
    }
    return inum + 1;
}

很容易将其扩展为使用负数。

您的问题要求返回int的函数,但通常ceil()函数返回与其参数相同的类型,因此范围没有问题(即float ceil(float num)) 。例如,如果num为1e20,则上述功能将失败。

答案 2 :(得分:7)

这基本上是你必须要做的,但没有转换为string

浮点数表示为(+/-) M * 2^E。指数E告诉你离二元点 * 有多远。如果E足够大,则没有小数部分,所以无所事事。如果E足够小,则没有整数部分,因此答案为1(假设M非零,且数字为正)。否则,E会告诉您尾数中出现二进制点的位置,您可以使用它进行检查,然后执行舍入。

<小时/> *不是小数点,因为我们在base-2,而不是base-10。

答案 3 :(得分:1)

我的5美分:

template <typename F>
constexpr inline auto ceil(F const f) noexcept
{
  auto const t(std::trunc(f));

  return t + (t < f);
}

答案 4 :(得分:0)

这样的事情:

  double param, fractpart, intpart;

  param = 3.14159265;
  fractpart = modf (param , &intpart);

  int intv = static_cast<int>(intpart); // can overflow - so handle that.

  if (fractpart > some_epsilon)
    ++intv;

您只需将some_epsilon值定义为您希望小数部分大于整数部分递增之前的值。其他需要考虑的事项是标志(即如果价值为负等)。

答案 5 :(得分:0)

它也适用于负值

int ma_ceil(float num)
{   int a = num;
    if ((float)a != num)
        return num+1;

    return num;
}

答案 6 :(得分:0)

以前的代码建议:

int ceil(float val) 
{
    int temp  = val * 10;
    if(val%10)
    return (temp+1);
    else
    return temp;
}

无法编译:在第4行“ if(val%10)”上收到“错误C2296:'%':非法,左操作数的类型为'float'”,因为您不能在以下位置使用mod运算符(%)浮动或双重。参见:Why we can't use operator % for float and double type operands? 它也不适用于精度不大于1/10的十进制值。

鉴于此,先前的代码建议:

int ma_ceil(float num)
{   int a = num;
    if ((float)a != num)
        return num+1;
    return num;
}
只要您不超出浮点值的范围,

就可以很好地工作。 num = 555555555; 要么 num = -5.000000001 除非您使用两次,否则将无法正常工作。

此外,因为浮点数和双精度数以IEEE浮点格式存储,所以存储的二进制表示形式可能不精确。例如:

浮点数= 5; 在某些情况下,可能不会获得分配的值5.0000000,而是5.9999998或5.00000001。 为了更正先前的代码版本,我建议将返回值更改为使用整数数学,而不是依赖浮点值的精度,如下所示:

int ma_ceil(float num)
{   int a = num;
    if ((float)a != num)
        return a+1;
    return a;
}

答案 7 :(得分:0)

这是一个负数的数字:

int ceil(float num) {
    int inum = (int)num;
    if (num < 0 || num == (float)inum) {
        return inum;
    }
    return inum + 1;
}

答案 8 :(得分:-5)

试试这个......

int ceil(float val)
{
    int temp  = val * 10;
    if(val%10)
    return (temp+1);
    else
    return temp;
}