【问题标题】:How to safely floor or ceil a CGFloat to int?如何安全地将 CGFloat 设置为 int?
【发布时间】:2012-08-13 04:55:11
【问题描述】:

我经常需要将CGFloat 设置为int,以计算数组索引。

我一直认为floorf(theCGFloat)ceilf(theCGFloat) 存在的问题是浮点数不准确可能存在问题。

如果我的CGFloat2.0f 但在内部它表示为1.999999999999f 或类似的东西怎么办。我做floorf 并得到1.0f,这又是一个浮点数。但是我必须将这个野兽转换为 int,这可能会引入另一个问题。

是否有最佳实践如何将float 设置为int,这样2.0 之类的东西永远不会意外地设置为1,而2.0 之类的东西永远不会意外地设置为2?

【问题讨论】:

  • 在提供描述输入值错误以及返回值过高或过低的后果的规范之前,无法正确回答此问题。在返回一个太高的值(因为先前的舍入误差使该值太高)和返回一个太低的值(因为该值被人为地调整以补偿先前的错误)之间存在权衡,反之亦然。没有上下文的解释,就没有一个正确的答案。

标签: ios math floating-point floating-accuracy floating-point-precision


【解决方案1】:

编辑 - 阅读 cmets 了解为什么这个答案不正确:)

float 转换为int 是隐式floorf,即(int)5.95。如果你不介意,那就投吧:)

如果你想四舍五入,那么只需转换 ceilf 的结果 - 在四舍五入之后进行转换根本不会引入任何错误(或者,如果你愿意,在转换之前添加一个,即 `(int)(5.9+ 1)' 是 '6' - 与向上取整相同)。

要四舍五入,只需添加 0.5 - (int)(5.9+0.5)6(int)(5.4+0.5)5。虽然我只会使用roundf(5.9) :)

【讨论】:

  • 将 float 转换为 int 不是隐含的地板。在 C 和其他一些常见语言中,它是一种截断(接近于零)。 Floor 在负无穷大的方向上四舍五入到最接近的整数。将 -3.5 转换为整数产生 -3,但 floor(-3.5) 为 -4。
  • 好的,这是一个公平的观点 - 我过于简单化到了错误的地步:)
【解决方案2】:

您的问题存在一些误解。

如果我的 CGFloat 是 2.0f 但在内部它表示为 1.999999999999f 会怎样

不可能发生; 2.0 和所有相当小的整数一样,具有浮点的精确表示。如果您的CGFloat2.0f,那么它确实是2.0。

2.0 之类的东西永远不会意外地被限制为 2

2.0的上限 2;还有什么可能?


我认为您真正要问的问题是“假设我进行的计算会产生不精确的结果,在数学上 应该 正好是 2.0,但实际上略少;当我应用 @ 987654323@ 到那个值,我得到的是 1.0 而不是 2.0——如何防止这种情况发生?”

这实际上是一个相当微妙的问题,没有一个“正确”的答案。你是如何计算输入值的?你打算如何处理结果?

【讨论】:

    【解决方案3】:

    Swift 补充答案

    对于那些来这里寻找如何将floorceilCGFloat 一起使用的人,我将其添加为补充答案(就像我一样)。

    var myCGFloat: CGFloat = 3.001
    floor(myCGFloat) // 3.0
    ceil(myCGFloat) // 4.0
    

    如果需要Int,则可以将其强制转换为一个。

    var myCGFloat: CGFloat = 3.001
    Int(floor(myCGFloat)) // 3
    Int(ceil(myCGFloat)) // 4
    

    更新

    不再需要使用 C floorceil 函数。您可以将 Swift round()rounding rules 一起使用。

    var myCGFloat: CGFloat = 3.001
    myCGFloat.round(.down) // 3.0
    myCGFloat.round(.up) // 4.0
    

    如果您不想修改原始变量,请使用rounded()

    备注

    • 适用于 32 位和 64 位架构。

    另请参阅

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-02
      • 2010-11-06
      • 2014-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-22
      • 2022-11-30
      相关资源
      最近更新 更多