在C中实现ceil() [英] Implement ceil() in C

查看:84
本文介绍了在C中实现ceil()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 C 中实现自己的 ceil().在库中搜索源代码&在此处找到,但似乎很难理解.我要清洁&精美的代码.

I want to implement my own ceil() in C. Searched through the libraries for source code & found here, but it seems pretty difficult to understand. I want clean & elegant code.

我也在SO上搜索,在此处找到了一些答案.答案似乎都不正确.答案之一是:

I also searched on SO, found some answer here. None of the answer seems to be correct. One of the answer is:

#define CEILING_POS(X) ((X-(int)(X)) > 0 ? (int)(X+1) : (int)(X))
#define CEILING_NEG(X) ((X-(int)(X)) < 0 ? (int)(X-1) : (int)(X))
#define CEILING(X) ( ((X) > 0) ? CEILING_POS(X) : CEILING_NEG(X) )

AFAIK, ceil()的返回类型不是int.宏在这里是类型安全的吗?此外,上述实现是否可以用于负数?

AFAIK, the return type of the ceil() is not int. Will macro be type-safe here? Further, will the above implementation work for negative numbers?

实现它的最佳方法是什么?

What will be the best way to implement it?

您能提供干净的代码吗?

Can you provide the clean code?

推荐答案

您引用的宏对于大于 INT_MAX 的数字绝对不能正确工作,但仍可以精确地表示为

The macro you quoted definitely won't work correctly for numbers that are greater than INT_MAX but which can still be represented exactly as a double.

正确地实现 ceil()的唯一方法(假设您不能使用等效的汇编指令来实现它)是对浮点数的二进制表示进行位扭曲这是在第一个链接后面的 s_ceil.c 源文件中完成的.了解代码的工作方式需要了解基础平台的浮点表示形式-该表示形式很可能将是

The only way to implement ceil() correctly (assuming you can't implement it using an equivalent assembly instruction) is to do bit-twiddling on the binary representation of the floating point number, as is done in the s_ceil.c source file behind your first link. Understanding how the code works requires an understanding of the floating point representation of the underlying platform -- the representation is most probably going to be IEEE 754 -- but there's no way around this.

s.ce_ceil.c 中的某些复杂性源于它处理的特殊情况(NaN,无穷大)以及它需要做的工作而又不能假定64位的事实.整型存在.

Some of the complexities in s_ceil.c stem from the special cases it handles (NaNs, infinities) and the fact that it needs to do its work without being able to assume that a 64-bit integral type exists.

所有位扭曲的基本思想是屏蔽尾数的小数位,如果数字大于零,则将尾数加1 ...但是还涉及一些附加逻辑以确保您在所有情况下都做对了.

The basic idea of all the bit-twiddling is to mask off the fractional bits of the mantissa and add 1 to it if the number is greater than zero... but there's a bit of additional logic involved as well to make sure you do the right thing in all cases.

这是 ceil()的说明性版本,用于我拼凑在一起的浮子.当心:这不会正确地处理特殊情况,并且未经广泛测试,因此请不要实际使用.但是,它确实可以说明位纠结中涉及的原理.我已经尝试过对该例程进行广泛的注释,但是这些注释确实假定您了解如何以IEEE 754格式表示浮点数.

Here's a illustrative version of ceil() for floats that I cobbled together. Beware: This does not handle the special cases correctly and it is not tested extensively -- so don't actually use it. It does however serve to illustrate the principles involved in the bit-twiddling. I've tried to comment the routine extensively, but the comments do assume that you understand how floating point numbers are represented in IEEE 754 format.

union float_int
{
    float f;
    int i;
};

float myceil(float x)
{
    float_int val;
    val.f=x;

    // Extract sign, exponent and mantissa
    // Bias is removed from exponent
    int sign=val.i >> 31;
    int exponent=((val.i & 0x7fffffff) >> 23) - 127;
    int mantissa=val.i & 0x7fffff;

    // Is the exponent less than zero?
    if(exponent<0) 
    {   
        // In this case, x is in the open interval (-1, 1)
        if(x<=0.0f)
            return 0.0f;
        else
            return 1.0f;
    }
    else
    {
        // Construct a bit mask that will mask off the
        // fractional part of the mantissa
        int mask=0x7fffff >> exponent;

        // Is x already an integer (i.e. are all the
        // fractional bits zero?)
        if((mantissa & mask) == 0)
            return x;
        else
        {
            // If x is positive, we need to add 1 to it
            // before clearing the fractional bits
            if(!sign)
            {
                mantissa+=1 << (23-exponent);

                // Did the mantissa overflow?
                if(mantissa & 0x800000)
                {
                    // The mantissa can only overflow if all the
                    // integer bits were previously 1 -- so we can
                    // just clear out the mantissa and increment
                    // the exponent
                    mantissa=0;
                    exponent++;
                }
            }

            // Clear the fractional bits
            mantissa&=~mask;
        }
    }

    // Put sign, exponent and mantissa together again
    val.i=(sign << 31) | ((exponent+127) << 23) | mantissa;

    return val.f;
}

这篇关于在C中实现ceil()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆