Как округлить CGFloat - PullRequest
       9

Как округлить CGFloat

18 голосов
/ 19 апреля 2010

Я сделал этот метод

+ (CGFloat) round: (CGFloat)f {
    int a = f;
    CGFloat b = a;
    return b;
}

Работает как положено, но только округляется. И если это отрицательное число, оно все еще округляется.

Это был только быстрый метод, который я сделал, не очень важно, чтобы он правильно округлялся, я просто сделал так, чтобы округлять значения x и y камеры для моей игры.

Этот метод в порядке? Это быстро? Или есть лучшее решение?

Ответы [ 6 ]

51 голосов
/ 14 января 2016

2018 Ответ

Другие ответы здесь либо датированы, либо не дают хороших примеров. 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, теперь устарели.
26 голосов
/ 19 апреля 2010

Уже есть стандартные функции с поведением, которые могут вам понадобиться в <math.h>, такие как: floorf, ceilf, roundf, rintf и nearbyintf (lasf 'f' означает версию "float", версии без нее - "двойные" версии).

Лучше использовать стандартные методы не только потому, что они стандартные, но и потому, что они лучше работают в крайних случаях.

Обновление 2013 (jessedc)

iOS больше не является только 32-битной. Есть ряд других ответов на этот вопрос, которые сейчас более актуальны.

В большинстве ответов упоминается импорт tgmath.h

5 голосов
/ 19 апреля 2010

A CGFloat - это typedef'd для double или float, поэтому вы можете округлить их, как и любой другой реальный тип:

CGFloat round(CGFloat aFloat)
{
    return (int)(aFloat + 0.5);
}

Обратите внимание, что, хотя это работает с плавающими числами, достаточно маленькими для переноса дроби, на больших значениях это может показаться странным.

1 голос
/ 07 июня 2013

Попробуйте #import "tgmath.h".

Заголовок <tgmath.h> будет содержать заголовки <math.h> и <complex.h> и определит несколько макросов общего типа.

0 голосов
/ 01 сентября 2014

Для работы с 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/64 битными значениями.

Определите это в файле, подобном MyMacros.h, а затем добавьте импорт в myapp-Prefix.pch

.

Также помните, что выбор CGFloat в качестве префикса для вашей функции может быть опасным, поскольку apple может добавить такой макрос самостоятельно, поэтому #ifndef CGFLOAT_CEIL равен

0 голосов
/ 19 апреля 2010

Вы заново изобретаете колесо - и это вопрос C, а не Цель C. Просто используйте стандартную функцию C round ().

...