Как безопасно надеть или погрузить CGFloat в int? - программирование

Как безопасно надеть или погрузить CGFloat в int?

Мне часто нужно заполнить CGFloat до int для вычисления индекса массива.

Проблема, которую я постоянно вижу с помощью floorf(theCGFloat) или ceilf(theCGFloat), заключается в том, что могут быть проблемы с неточностями с плавающей запятой.

Так что, если мой CGFloat 2.0f, но внутри он представлен как 1.999999999999f или что-то в этом роде. Я делаю floorf и получаю 1.0f, который снова является поплавком. И все же я должен бросить этого зверя в int, который может ввести еще одну проблему.

Есть ли наилучшая практика для того, как настил или поместить float в int так, чтобы что-то вроде 2.0 никогда не попадалось бы наподобие 1, а что-то вроде 2.0 никогда не будет случайно закрыто 2?

4b9b3361

Ответ 1

В вашем вопросе есть пара неправильных представлений.

что, если мой CGFloat 2.0f, но внутренне он представлен как 1.999999999999f

не может случиться; 2.0, как и все достаточно мелкие целые числа, имеет точное представление в плавающей запятой. Если ваш CGFloat равен 2.0f, тогда это действительно 2.0.

что-то вроде 2.0 никогда не будет случайно потеряно до 2

Потолок 2.0 равен 2; что еще может быть?


Я думаю, что вопрос, который вы действительно задаете, "предположим, что я делаю расчет, который дает неточный результат, который математически должен быть ровно 2.0, но на самом деле немного меньше, когда я применяю floor к этому значению, я get 1.0 вместо 2.0 - как это предотвратить?"

Это действительно довольно тонкий вопрос, который не имеет ни одного "правильного" ответа. Как вы вычислили входное значение? Что вы собираетесь делать с результатом?

Ответ 2

Быстрый дополнительный ответ

Я добавляю это как дополнительный ответ для тех, кто приходит сюда, глядя, как использовать floor и ceil с помощью CGFloat (как и я).

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 floor и ceil. Вы можете использовать правила Swift round() с округления.

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

Если вы не хотите изменять исходные переменные, используйте rounded().

Примечания

  • Работает как с 32, так и с 64-разрядными архитектурами.

См. также

Ответ 3

EDIT - прочитайте комментарии по причинам, почему этот ответ неверен:)

Приведение a float в int является неявным floorf i.e. (int)5.9 is 5. Если вы не возражаете, тогда просто бросьте:)

Если вы хотите округлить, просто произведите результат ceilf - casting после округления, не должны вводить никаких ошибок вообще (или, если хотите, добавить один перед литьем, т.е. `(int) (5.9+ 1) 'is' 6 '- то же, что и округление).

Чтобы округлить до ближайшего, просто добавьте 0.5 - (int)(5.9+0.5) is 6, но (int)(5.4+0.5) - 5. Хотя я бы просто использовал roundf(5.9):)