Функция Ceil: как мы можем реализовать ее сами?
Я знаю, что C++ предоставляет нам функцию ceil. Для практики мне было интересно, как мы можем реализовать функцию ceil в C++. Подпись метода public static int ceil (float num)
пожалуйста, дайте некоторое представление.
Я подумал о простом способе: преобразовать num в строку, Найти индекс десятичной точки, проверить, если десятичная часть больше 0. Если да, верните num+1 еще верните num. Но я хочу избежать использования преобразования строки
6 ответов
вот наивная реализация для положительных чисел (это использует тот факт, что приведение к (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
is 1e20.
вы можете разобрать ингредиенты числа с плавающей запятой 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;
}
(вставьте здесь обычную оговорку" не переносится".)
это именно то, что вам нужно сделать, но без преобразования в string
.
число с плавающей точкой представляется как (+/-) M * 2^E
. Экспонента,E
, говорит вам, как далеко вы находитесь от двоичной точки*. Если E
достаточно большой, дробной части нет, поэтому делать нечего. Если E
достаточно мал, целочисленной части нет, поэтому ответ 1 (при условии M
является ненулевым, и число является положительным). В противном случае, E
указывает, где двоичная точка появляется в пределах вашей мантиссы, которую можно использовать для проверки, а затем выполнить округление.
* не десятичная точка, потому что мы находимся в базе-2, а не в базе-10.
что-то вроде этого:
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
значение для того, что вы хотите, чтобы дробная часть была больше, чем до увеличения целочисленной части. Другие вещи, чтобы рассмотреть знак (т. е. если значение отрицательное и т. д.)
он работает с отрицательным значением тоже
int ma_ceil(float num)
{ int a = num;
if ((float)a != num)
return num+1;
return num;
}
попробуйте это...
int ceil(float val)
{
int temp = val * 10;
if(val%10)
return (temp+1);
else
return temp;
}