ios 如何安全地将 CGFloat 设置为 int 或 ceil?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11993981/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:45:04  来源:igfitidea点击:

How to safely floor or ceil a CGFloat to int?

iosmathfloating-pointfloating-accuracyfloating-point-precision

提问by Proud Member

I often need to floor or ceil a CGFloatto an int, for calculation of an array index.

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

The problem I permanently see with floorf(theCGFloat)or ceilf(theCGFloat)is that there can be troubles with floating point inaccuracies.

我看到永久的问题floorf(theCGFloat)或者ceilf(theCGFloat)是有可与浮点不准确的麻烦。

So what if my CGFloatis 2.0fbut internally it is represented as 1.999999999999for something like that. I do floorfand get 1.0f, which is a float again. And yet I must cast this beast to int which may introduce another problem.

那么,如果我CGFloat是,2.0f但在内部它被表示为1.999999999999f或类似的东西。I do floorfand get 1.0f,这又是一个浮点数。然而我必须将这个野兽转换为 int ,这可能会引入另一个问题。

Is there a best practice how to floor or ceil a floatto an intsuch that something like 2.0would never accidentally get floored to 1and something like 2.0would never accidentally get ceiled to 2?

是否有最佳实践如何将 a 限制float在 a 上int,以便像2.0这样的1东西2.0永远不会意外地被踩到,而像这样的东西永远不会意外地被限制到2

回答by Suragch

Swift supplemental answer

快速补充答案

I am adding this as a supplemental answer for those who come here looking how to use floorand ceilwith a CGFloat(like I did).

我将此添加为那些来这里寻找如何使用floorceil使用CGFloat(就像我一样)的人的补充答案。

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

And if an Intis needed, then it can be cast to one.

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

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

Update

更新

There is no need to use the C floorand ceilfunctions anymore. You can use the Swift round()with rounding rules.

不再需要使用 Cfloorceil函数。您可以使用round()带有舍入规则的 Swift 。

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

If you don't wish to modify the original variables, then use rounded().

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

Notes

笔记

  • Works with both 32 and 64 bit architectures.
  • 适用于 32 位和 64 位架构。

See also

也可以看看

回答by Stephen Canon

There are a couple misconceptions in your question.

你的问题有几个误解。

what if my CGFloat is 2.0f but internally it is represented as 1.999999999999f

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

can't happen; 2.0, like all reasonably small integers, has an exact representation in floating-point. If your CGFloatis 2.0f, then it really is 2.0.

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

something like 2.0 would never accidentally get ceiled to 2

像 2.0 这样的东西永远不会意外地被限制到 2

The ceiling of 2.0 is2; what else would it possibly be?

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



I think the question that you're really asking is "suppose I do a calculation that produces an inexact result, which mathematically shouldbe exactly 2.0, but is actually slightly less; when I apply floorto that value, I get 1.0 instead of 2.0--how do I prevent this?"

我认为您真正要问的问题是“假设我进行的计算产生了不精确的结果,从数学上讲,该结果应该正好是 2.0,但实际上略小;当我应用floor该值时,我得到 1.0 而不是 2.0- ——我该如何预防?”

That's actually a fairly subtle question that doesn't have a single "right" answer. How have you computed the input value? What are you going to do with the result?

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

回答by deanWombourne

EDIT - read the comments for reasons why this answer isn't right :)

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

Casting a floatto an intis an implicit floorfi.e. (int)5.9is 5. If you don't mind that then just cast :)

将 a 转换float为 anint是一个隐式的floorfie (int)5.9is 5。如果你不介意,那就投吧:)

If you want to round up then just cast the result of a ceilf- casting after rounding shouldn't introduce any errors at all (or, if you want, add one before casting i.e. `(int)(5.9+1)' is '6' - same as rounding up).

如果你想四舍五入,那么只需ceilf在四舍五入后转换 - 转换的结果根本不应该引入任何错误(或者,如果你想,在转换之前添加一个,即`(int)(5.9+1)' is '6 ' - 与四舍五入相同)。

To round to the nearest, just add 0.5 - (int)(5.9+0.5)is 6but (int)(5.4+0.5)is 5. Though I would just use roundf(5.9):)

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