Как округлить 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

Down

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

Up

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