В чем разница между использованием CGFloat и float?
169
Я склонен использовать CGFloat повсеместно, но мне интересно, получу ли я бессмысленный «удар по производительности» с этим. CGFloat кажется чем-то «тяжелее», чем float, верно? В каких точках я должен использовать CGFloat, и что действительно меняет дело?
Как сказал @weichsel, CGFloat - это просто typedef для обоих floatили double. Вы можете убедиться в этом, дважды щелкнув Command на «CGFloat» в Xcode - он перейдет к заголовку CGBase.h, где определен typedef. Тот же подход используется и для NSInteger и NSUInteger.
Эти типы были введены для упрощения написания кода, который работает как на 32-битной, так и на 64-битной версии без изменений. Однако, если все, что вам нужно, это floatточность в вашем собственном коде, вы все равно можете использовать его, floatесли хотите - это несколько уменьшит объем используемой памяти. То же самое касается целочисленных значений.
Я предлагаю вам потратить скромное время, необходимое для того, чтобы сделать приложение 64-разрядным, и попытаться запустить его как таковое, поскольку большинство компьютеров Mac теперь имеют 64-разрядные процессоры, а Snow Leopard полностью 64-разрядный, включая ядро и пользовательские приложения. 64-битное руководство Apple по переходу на какао является полезным ресурсом.
Я думаю, я понял это сейчас. Но на iPhone это, кажется, не имеет большого значения, верно?
4
На айфон, как мы его знаем, нет. Однако всегда разумно использовать код, ориентированный на будущее, и это облегчит безопасное повторное использование одного и того же кода для OS X.
Куинн Тейлор,
Таким образом, вы говорите, в основном, НИКОГДА не используйте float или double напрямую, так как тогда вы будете привязаны к архитектуре процессора (и я думал, что быстрые JVM решат это несколько лет назад :)). Так какие примитивы безопасны? int?
Дэн Розенстарк
9
Я не говорил НИКОГДА не использовать примитив напрямую. Иногда прямые примитивы могут быть проблематичными, например, если переменная может использоваться для хранения данных, которые могут переполниться, например, в 64-битной среде. В целом, использование зависящих от архитектуры typedefs безопаснее, так как этот код с меньшей вероятностью взорвется на другой архитектуре. Однако иногда использование 32-битного типа может быть абсолютно безопасным и сэкономить вашу память. Размер примитивов может быть меньшей проблемой в JVM, но Obj-C и C компилируются, и смешивание 32- и 64-битных библиотек и кода действительно проблематично.
Куинн Тейлор
1
@QuinnTaylor Можете ли вы привести практический пример того, как float переполняется, а CGFloat - нет? И float, и CGFloat имеют конечное число битов. Вы можете переполнить их, храня больше битов, чем они могут содержать.
Pwner
76
CGFloat - это обычное число с плавающей точкой в 32-битных системах и двойное число в 64-битных системах.
Ну, вы используете вдвое больше памяти, если беспокоитесь о памяти.
Тайлер
8
Только на 64-битной.
Куинн Тейлор
13
Правильно, iPhone OS 32-битная. Если подумать, iPhone не использует ограничение 32 ГБ ОЗУ в 4 ГБ и не использует процессор Intel (для которого 64-разрядная скорость быстрее, чем 32-разрядная). Кроме того, он использует Modern Runtime (в отличие от Legacy Runtime 32-разрядных на настольном компьютере - для этих терминов достаточно SO), поэтому он может делать практически все, что может 64-разрядная OS X. Возможно, когда-нибудь мы увидим устройство, которое работает под управлением iPhone OS и является 64-битным, но в настоящее время его нет.
Куинн Тейлор
23
Введите: iPhone 5S
Dgund
7
5S сейчас находится в 64-битном режиме, в последний раз, когда я входил на конференцию (Лондон), они сказали, что способ запуска 32-битных приложений на ios7 - это запуск другого пула общего кэша в памяти, что может привести к увеличению общего объема памяти. так что его def стоит конвертировать все до 64 бит. (если вы не хотите поддерживать 5.1+ или 6.0+ до сих пор)
phil88530
2
Как уже говорили другие, CGFloat является плавающей точкой на 32-битных системах и двойной на 64-битных системах. Однако решение сделать это было унаследовано от OS X, где оно было принято на основе характеристик производительности ранних процессоров PowerPC. Другими словами, вы не должны думать, что float предназначен для 32-битных процессоров, а double - для 64-битных процессоров. (Я полагаю, что процессоры ARM от Apple смогли обработать удвоения задолго до того, как они стали 64-разрядными.) Основной удар по производительности при использовании двойников заключается в том, что они используют вдвое больше памяти и, следовательно, могут работать медленнее, если вы выполняете много операций с плавающей запятой. ,
Где __LP64__указывает, является ли текущая архитектура * 64-битной.
Обратите внимание, что 32-разрядные системы по-прежнему могут использовать 64-разрядные double, просто требуется больше процессорного времени, поэтому CoreGraphics делает это для целей оптимизации, а не для совместимости. Если вы не беспокоитесь о производительности, но беспокоитесь о точности, просто используйте double.
стриж
В Swift CGFloatэто structоболочка Floatдля 32-битных или Double64 -битных архитектур (вы можете обнаружить это во время выполнения или во время компиляции CGFloat.NativeType)
publicstructCGFloat{#ifarch(i386)||arch(arm)/// The native type used to store the CGFloat, which is Float on
/// 32-bit architectures and Double on 64-bit architectures.
publictypealiasNativeType=Float#elseif arch(x86_64)||arch(arm64)/// The native type used to store the CGFloat, which is Float on
/// 32-bit architectures and Double on 64-bit architectures.
publictypealiasNativeType=Double#endif
просто упомянуть, что - январь 2020 года Xcode 11.3 / iOS13
Swift 5
Из исходного кода CoreGraphics
publicstructCGFloat{/// The native type used to store the CGFloat, which is Float on/// 32-bit architectures and Double on 64-bit architectures.public typealias NativeType=Double
int
?CGFloat - это обычное число с плавающей точкой в 32-битных системах и двойное число в 64-битных системах.
Таким образом, вы не получите никакого штрафа за производительность.
источник
Как уже говорили другие, CGFloat является плавающей точкой на 32-битных системах и двойной на 64-битных системах. Однако решение сделать это было унаследовано от OS X, где оно было принято на основе характеристик производительности ранних процессоров PowerPC. Другими словами, вы не должны думать, что float предназначен для 32-битных процессоров, а double - для 64-битных процессоров. (Я полагаю, что процессоры ARM от Apple смогли обработать удвоения задолго до того, как они стали 64-разрядными.) Основной удар по производительности при использовании двойников заключается в том, что они используют вдвое больше памяти и, следовательно, могут работать медленнее, если вы выполняете много операций с плавающей запятой. ,
источник
Objective-C
Из исходного кода Foundation, в CoreGraphics '
CGBase.h
:Авторское право (c) 2000-2011 Apple Inc.
Это по существу делает:
Где
__LP64__
указывает, является ли текущая архитектура * 64-битной.Обратите внимание, что 32-разрядные системы по-прежнему могут использовать 64-разрядные
double
, просто требуется больше процессорного времени, поэтому CoreGraphics делает это для целей оптимизации, а не для совместимости. Если вы не беспокоитесь о производительности, но беспокоитесь о точности, просто используйтеdouble
.стриж
В Swift
CGFloat
этоstruct
оболочкаFloat
для 32-битных илиDouble
64 -битных архитектур (вы можете обнаружить это во время выполнения или во время компиляцииCGFloat.NativeType
)Из исходного кода CoreGraphics, в
CGFloat.swift.gyb
:* Конкретно,
long
s и указатели, отсюдаLP
. Смотрите также: http://www.unix.org/version2/whatsnew/lp64_wp.htmlисточник
просто упомянуть, что - январь 2020 года Xcode 11.3 / iOS13
Swift 5
Из исходного кода CoreGraphics
источник