21

我做了这个方法

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

它按预期工作,但只会四舍五入。如果它是一个负数,它仍然向下舍入。

这只是我制作的一种快速方法,它是否正确舍入并不是很重要,我只是为我的游戏舍入了相机的 x 和 y 值。

这个方法好吗?快吗?还是有更好的解决方案?

4

6 回答 6

66

2018年答案

这里的其他答案要么过时,要么没有给出很好的例子。CGFloat使用 Swift 的内置rounded函数很容易对 a 进行舍入。

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.5or -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

笔记

  • 不要忘记考虑负值。
  • 结果roundrounded仍然CGFloat。如果您需要一个Int,则必须将其转换为Int(myCGFloat).
  • 不再需要使用 C 数学函数round(x)。但是,如果您确实使用它们,它们会同时处理 64 位和 32 位架构,因此您可能已经看到的任何答案现在都已过时。ceil(x)floor(x)roundfceilffloorf
于 2016-01-14T08:47:28.607 回答
28

已经有标准函数具有您可能需要的行为,例如 <math.h>floorf、、、和(lasf 'f' 表示“浮动”版本,没有它的版本是“双”版本)。ceilfroundfrintfnearbyintf

最好使用标准方法,不仅因为它们是标准的,而且因为它们在极端情况下工作得更好。

2013 年更新 (jessedc)

iOS 不再只有 32 位。这个问题还有许多其他答案现在更相关。

大多数答案提到导入tgmath.h

于 2010-04-19T12:10:20.603 回答
5

ACGFloat类型定义为 adouble或 a float,因此您可以像任何其他真实类型一样将它们四舍五入:

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

请注意,虽然这适用于小到足以携带分数的浮点数,但它可能对大值产生奇怪的作用。

于 2010-04-19T12:02:33.463 回答
1

您正在重新发明轮子 - 这是一个 C 问题,而不是 Objective C。只需使用标准 C 的 round() 函数。

于 2010-04-19T12:10:22.493 回答
1

试试#import "tgmath.h"

<tgmath.h>头将包括标头<math.h><complex.h>并将定义几个类型通用的宏。

于 2013-06-07T14:12:19.090 回答
0

对于 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 作为函数的前缀可能是有风险的,因为苹果可能会添加一个像他们自己这样的宏,这就是为什么 #ifndef CGFLOAT_CEIL 是

于 2014-09-01T09:18:54.293 回答