Как округлить CGFloat
Я сделал этот метод
+ (CGFloat) round: (CGFloat)f {
int a = f;
CGFloat b = a;
return b;
}
Он работает как ожидалось, но он только округляется. И если это отрицательное число, оно все равно округляется.
Это был просто быстрый метод, который я сделал, это не очень важно, чтобы он округлился правильно, я просто сделал это для округления значений камеры x и y для моей игры.
Этот метод в порядке? Это быстро? Или есть лучшее решение?
Ответы
Ответ 1
Существуют уже стандартные функции с поведением, которые могут потребоваться в <math.h>
, например: floorf
, ceilf
,
roundf
, rintf
и nearbyintf
(lasf 'f' означает версию с плавающей запятой, версии без нее - это "двойные" версии).
Лучше использовать стандартные методы не только потому, что они являются стандартными, но и потому, что они лучше работают в случаях кросс.
Обновление 2013 года (jessedc)
iOS уже не 32 бит. Есть ряд других ответов на этот вопрос, которые теперь более актуальны.
В большинстве ответов упоминается импорт tgmath.h
Ответ 2
2017 Ответ
Другие ответы здесь датированы или не дают хороших примеров. Легко округлить CGFloat
с помощью Swift, встроенного в функцию rounded
.
let x: CGFloat = 3.5
let y = x.rounded() // 4.0
Если вы хотите округлить значение, вы можете использовать round
:
var x: CGFloat = 3.5
x.round() // 4.0
Правила округления
Если вам нужен более точный контроль над округлением чисел, вы можете использовать FloatingPointRoundingRule
.
x.rounded(.awayFromZero)
Числа выше нуля округляются, а числа ниже нуля округляются вниз.
3.000 -> 3.0
3.001 -> 4.0
3.499 -> 4.0
3.500 -> 4.0
3.999 -> 4.0
-3.000 -> -3.0
-3.001 -> -4.0
-3.499 -> -4.0
-3.500 -> -4.0
-3.999 -> -4.0
x.rounded(.down)
Устанавливает любое число с десятичным значением до следующего меньшего целого числа. Это то же самое, что и floor(x)
.
3.000 -> 3.0
3.001 -> 3.0
3.499 -> 3.0
3.500 -> 3.0
3.999 -> 3.0
-3.000 -> -3.0
-3.001 -> -4.0
-3.499 -> -4.0
-3.500 -> -4.0
-3.999 -> -4.0
x.rounded(.toNearestOrAwayFromZero) // same as x.rounded()
Десятичные числа округляются до ближайшего целочисленного значения. Однако, когда значение находится точно в середине (например, 3.5
или -3.5
), положительные числа округляются, а отрицательные числа округляются вниз.
У него может быть длинное сложное имя, но обычно это так, как учиться округлять в школе. Это также правило используется, если вы просто делаете x.rounded()
.
3.000 -> 3.0
3.001 -> 3.0
3.499 -> 3.0
3.500 -> 4.0 ***
3.999 -> 4.0
-3.000 -> -3.0
-3.001 -> -3.0
-3.499 -> -3.0
-3.500 -> -4.0 ***
-3.999 -> -4.0
x.rounded(.toNearestOrEven)
Это похоже на toNearestOrAwayFromZero
, за исключением того, что теперь значения .5
округляются до четного целого числа.
3.000 -> 3.0
3.001 -> 3.0
3.499 -> 3.0
3.500 -> 4.0 ***
3.999 -> 4.0
4.500 -> 4.0 ***
-3.000 -> -3.0
-3.001 -> -3.0
-3.499 -> -3.0
-3.500 -> -4.0 ***
-3.999 -> -4.0
-4.500 -> -4.0 ***
x.rounded(.towardZero)
Это просто приводит к отключению любых десятичных значений. Если вам нужен Int
, вы можете сделать то же самое с Int(x)
.
3.000 -> 3.0
3.001 -> 3.0
3.499 -> 3.0
3.500 -> 3.0
3.999 -> 3.0
-3.000 -> -3.0
-3.001 -> -3.0
-3.499 -> -3.0
-3.500 -> -3.0
-3.999 -> -3.0
x.rounded(.up)
Это противоположность .down
. Все десятичные числа округлены. Это то же самое, что и ceil(x)
.
3.000 -> 3.0
3.001 -> 4.0
3.499 -> 4.0
3.500 -> 4.0
3.999 -> 4.0
-3.000 -> -3.0
-3.001 -> -3.0
-3.499 -> -3.0
-3.500 -> -3.0
-3.999 -> -3.0
Примечания
- Не забывайте учитывать отрицательные значения.
- Результаты
round
и rounded
все еще CGFloat
. Если вам нужен Int
, вам нужно преобразовать его как Int(myCGFloat)
.
- Нет необходимости использовать математические функции C
round(x)
, ceil(x)
и floor(x)
. Однако, если вы их используете, они обрабатывают как 64-битную, так и 32-битную архитектуру, поэтому любые ответы, которые вы, возможно, видели с помощью roundf
, ceilf
и floorf
, теперь устарели.
Ответ 3
A CGFloat
является typedef'd либо a double
, либо float
, поэтому вы можете объединять их, как и любой другой реальный тип:
CGFloat round(CGFloat aFloat)
{
return (int)(aFloat + 0.5);
}
Обратите внимание, что, хотя это работает с поплавками, достаточно маленькими, чтобы нести долю, она может действовать странно при больших значениях.
Ответ 4
Попробуйте #import "tgmath.h"
.
Заголовок <tgmath.h>
будет содержать заголовки <math.h>
и <complex.h>
и будет определять несколько макросов типа.
Ответ 5
Вы изобретаете колесо - и это вопрос C, а не Objective C. Просто используйте стандартную функцию C round().
Ответ 6
Для работы с 32 и 64 бит вы можете создать свой собственный макрос, например
#ifndef CGFLOAT_CEIL
#ifdef CGFLOAT_IS_DOUBLE
#define CGFLOAT_CEIL(value) ceil(value)
#else
#define CGFLOAT_CEIL(value) ceilf(value)
#endif
#endif
Ps это не ответ на вопрос, а дополнение к вопросу о том, как работать с 32-битными значениями.
Определите это в файле, например MyMacros.h, и добавьте импорт в myapp-Prefix.pch
Также помните, что выбор CGFloat как префикса для вашей функции может быть риском, так как яблоко могло бы добавить макрос, подобный этому, так что поэтому #ifndef CGFLOAT_CEIL