C++ Ceil 函数:我们如何自己实现?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8377412/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ceil function: how can we implement it ourselves?
提问by TimeToCodeTheRoad
I know that C++ provides us with a ceil function. For practice, I was wondering how can we implement the ceil function in C++. The signature of the method is public static int ceil(float num)
我知道 C++ 为我们提供了一个 ceil 函数。为了练习,我想知道我们如何在 C++ 中实现 ceil 函数。方法的签名是 public static int ceil(float num)
Please provide some insight.
请提供一些见解。
I thought of a simple way: Convert num to a string, find the index of the decimal point, check if the decimal part is greater than 0. If yes, return num+1 else return num. But I want to avoid using the string conversion
我想到了一个简单的方法:将num转换为字符串,找到小数点的索引,检查小数部分是否大于0。如果是,则返回num+1,否则返回num。但我想避免使用字符串转换
采纳答案by Greg Hewgill
Here is a naive implementation for positive numbers (this uses the fact that casting to (int)
truncates toward zero):
这是正数的一个简单实现(这使用了强制转换为(int)
向零截断的事实):
int ceil(float num) {
int inum = (int)num;
if (num == (float)inum) {
return inum;
}
return inum + 1;
}
It is easy to extend this to work with negative numbers too.
很容易将其扩展到负数。
Your question asked for a function returning int
, but normally the ceil()
function returns the same type as its argument so there are no problems with the range (that is, float ceil(float num)
). For example, the above function will fail if num
is 1e20.
您的问题要求函数返回int
,但通常该ceil()
函数返回与其参数相同的类型,因此范围(即float ceil(float num)
)没有问题。例如,如果num
是 1e20 ,上面的函数就会失败。
回答by fredoverflow
You can take apart the ingredients of an IEEE754 floating point number and implement the logic yourself:
您可以分解 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;
}
(Insert the usual "not portable" disclaimer here.)
(在此处插入通常的“不可移植”免责声明。)
回答by Oliver Charlesworth
That is essentially what you have to do, but without converting to string
.
这基本上是您必须做的,但无需转换为string
.
A floating-point number is represented as (+/-) M * 2^E
. The exponent, E
, tells you how far away you are from the binary point*. If E
is big enough, there is no fractional part, so there's nothing to do. If E
is small enough, there is no integer part, so the answer is 1 (assuming M
is non-zero, and the number is positive). Otherwise, E
tells you where the binary point appears within your mantissa, which you can use to do a check, and then perform rounding.
浮点数表示为(+/-) M * 2^E
。指数 ,E
告诉您距离二进制小数点*有多远。如果E
足够大,则没有小数部分,因此无事可做。如果E
足够小,则没有整数部分,因此答案为 1(假设M
非零,并且数字为正)。否则,E
告诉您二进制小数点出现在尾数中的哪个位置,您可以使用它进行检查,然后执行舍入。
* Not decimal point, because we're in base-2, not base-10.* 不是小数点,因为我们以 2 为基数,而不是以 10 为基数。
回答by user1095108
My 5 cents:
我的 5 美分:
template <typename F>
constexpr inline auto ceil(F const f) noexcept
{
auto const t(std::trunc(f));
return t + (t < f);
}
回答by chris
it works with negative value too
它也适用于负值
int ma_ceil(float num)
{ int a = num;
if ((float)a != num)
return num+1;
return num;
}
回答by David M
The previous code recommendation:
之前的代码推荐:
int ceil(float val)
{
int temp = val * 10;
if(val%10)
return (temp+1);
else
return temp;
}
does not compile: Receives "error C2296: '%': illegal, left operand has type 'float'" on line 4 "if(val%10)" because you can't use the mod operator (%) on a float or double. See: Why we can't use operator % for float and double type operands?It also does not work for decimal values whose precision is not greater than 1/10.
不编译:在第 4 行“if(val%10)”上收到“错误 C2296: '%': 非法,左操作数的类型为 'float'”,因为您不能在浮点数上使用 mod 运算符 (%) 或双倍的。请参阅:为什么我们不能将运算符 % 用于 float 和 double 类型操作数?它也不适用于精度不大于 1/10 的十进制值。
Whereas, the prior code recommendation:
而先前的代码建议:
int ma_ceil(float num)
{ int a = num;
if ((float)a != num)
return num+1;
return num;
}
works well, as long as you don't go beyond the bounds of a floating point value. num = 555555555; or num = -5.000000001 are not going to work unless you use a double.
效果很好,只要您不超出浮点值的范围。数量 = 555555555; 或 num = -5.000000001 不会起作用,除非您使用双精度数。
Also, because floats and doubles are stored in IEEE floating point format, the binary representations stored can be inexact. For, instance:
此外,由于浮点数和双精度数以 IEEE 浮点格式存储,因此存储的二进制表示可能不准确。例如:
float num = 5; in some instances might not get the value 5.0000000 assigned, but rather 5.9999998 or 5.00000001. To correct the prior code version, I'd recommended changing the return value to use integer math rather than relying on the accuracy of the floating point value, as follows:
浮点数 = 5; 在某些情况下,可能不会得到 5.0000000 分配的值,而是 5.9999998 或 5.00000001。为了更正之前的代码版本,我建议更改返回值以使用整数数学而不是依赖于浮点值的准确性,如下所示:
int ma_ceil(float num)
{ int a = num;
if ((float)a != num)
return a+1;
return a;
}
回答by Nim
Something like this:
像这样的东西:
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;
You just need to define some_epsilon
value to whatever you want the fractional part to be bigger than before the integer part is incremented. Other things to consider are sign (i.e. if the value is negative etc.)
您只需要将some_epsilon
值定义为您希望小数部分大于整数部分增加之前的任何值。其他要考虑的事情是符号(即如果值为负等)
回答by Veer Bahadur Singh
Try this...
尝试这个...
int ceil(float val)
{
int temp = val * 10;
if(val%10)
return (temp+1);
else
return temp;
}