取 CGFloat 的绝对值
Posted
技术标签:
【中文标题】取 CGFloat 的绝对值【英文标题】:taking absolute value of CGFloat 【发布时间】:2013-01-16 01:08:43 【问题描述】:我该怎么做?我尝试了 abs() 但它只适用于 int。有内置的方法吗?
CGFloat flo = -123;
abs(flo)
返回 0
【问题讨论】:
标准 'abs' 函数在 Swift 4 中效果很好 【参考方案1】:使用 fabs()
CGFloat f = -123.4f;
CGFloat g = fabs(f);
CGFloat
在 64 位机器上定义为 double
,在 32 位机器上定义为 float
。如果您同时针对 64 位和 32 位,则此答案会变得更复杂,但仍然正确。
您想使用fabs()
,因为它适用于大于float
的double
数据类型。在 32 位上,仅当您采用 CGFloat
的绝对值或float
。如果您尝试存储大 double
数字的绝对值,您可能会溢出 32 位 CGFloat
。简而言之,64 位就可以了,在 32 位上不要混用 double
和 CGFloat
就可以了。
ABS()
宏显然会对某些编译器产生副作用。
【讨论】:
正确 (+1),但打印值或进行分配。 CGFloat 是浮点型或双精度型(32/64 位系统)的类型定义。 fabs 需要双倍(至少在我的 xcode 中,这就是它想要的)。那么这样会安全吗? 由于 CGFloat 可以定义为双精度或浮点数,因此很难说这是正确的答案:fabsf 期望浮点数作为输入参数,fabs 总是返回双精度数。建议在 32 位/64 位环境(如今天的手机)中使用 std::abs() 或宏 ABS()。 这在 64 位 ios 中不再正确,您会收到语义问题警告:Absolute value function 'fabsf' given an argument of type 'CGFloat' (aka 'double') but has parameter of type 'float' which may cause truncation of value
您能否扩展您关于ABS()
对某些编译器有副作用的最后评论?哪些编译器?如果我坚持使用 Xcode,它是否完全安全?【参考方案2】:
对于 64/32 位系统
#if CGFLOAT_IS_DOUBLE
CGFloat g = fabs(flo);
#else
CGFloat g = fabsf(flo);
#endif
【讨论】:
这是最好的答案,而不是制作自己的宏包装器。除此之外,请确定您是否真的需要担心任何 32 位平台。 这正是 Skela 在另一个答案中所说的预定义宏 ABS 的用途。【参考方案3】:据我所知,我通常只使用 ABS 宏,无论您使用哪个系统或使用哪个原语,它都可以工作。
CGFloat x = -1.1;
double y = -2.1;
NSInteger z = -5;
x = ABS(x);
y = ABS(y);
z = ABS(z);
【讨论】:
【参考方案4】:小补充:
CGFloat g = fabs(f);
这将导致强制转换警告,因为 fabs() 返回一个双精度值。 要返回浮点值,您需要使用 fabsf()。
CGFloat g = fabsf(f);
【讨论】:
【参考方案5】:fabs
已折旧。 abs
的签名现在与此签名通用
/// Returns the absolute value of the given number.
///
/// The absolute value of `x` must be representable in the same type. In
/// particular, the absolute value of a signed, fixed-width integer type's
/// minimum cannot be represented.
///
/// let x = Int8.min
/// // x == -128
/// let y = abs(x)
/// // Overflow error
///
/// - Parameter x: A signed number.
/// - Returns: The absolute value of `x`.
@inlinable public func abs<T>(_ x: T) -> T where T : Comparable, T : SignedNumeric
【讨论】:
以上是关于取 CGFloat 的绝对值的主要内容,如果未能解决你的问题,请参考以下文章