Apa perbedaan antara menggunakan CGFloat dan float?

169

Saya cenderung menggunakan CGFloat di mana-mana, tetapi saya ingin tahu apakah saya mendapatkan "kinerja yang tidak masuk akal" dengan ini. CGFloat tampaknya menjadi sesuatu yang "lebih berat" daripada float, bukan? Di titik mana saya harus menggunakan CGFloat, dan apa yang membuat perbedaan?


sumber

Jawaban:

193

Seperti yang dikatakan @weichsel, CGFloat hanyalah sebuah typedef untuk salah satu floatatau double. Anda dapat melihat sendiri dengan mengklik ganda Command pada "CGFloat" di Xcode - itu akan melompat ke header CGBase.h di mana typedef didefinisikan. Pendekatan yang sama digunakan untuk NSInteger dan NSUInteger juga.

Jenis ini diperkenalkan untuk membuatnya lebih mudah untuk menulis kode yang berfungsi pada 32-bit dan 64-bit tanpa modifikasi. Namun, jika semua yang Anda butuhkan adalah floatketepatan dalam kode Anda sendiri, Anda masih dapat menggunakannya floatjika Anda mau - itu akan mengurangi jejak memori Anda. Hal yang sama berlaku untuk nilai integer.

Saya sarankan Anda menginvestasikan waktu sederhana yang diperlukan untuk membuat aplikasi Anda 64-bit bersih dan coba jalankan seperti itu, karena sebagian besar Mac sekarang memiliki CPU 64-bit dan Snow Leopard sepenuhnya 64-bit, termasuk aplikasi kernel dan pengguna. Panduan Transisi 64-bit Apple untuk Kakao adalah sumber yang bermanfaat.

Quinn Taylor
sumber
Saya rasa saya mengerti sekarang. Tapi di iPhone sepertinya tidak terlalu masalah, kan?
4
Di iPhone seperti yang kita tahu, tidak. Namun, selalu bijaksana untuk kode bukti masa depan, dan ini akan membuatnya lebih mudah untuk menggunakan kembali kode yang sama untuk OS X.
Quinn Taylor
jadi Anda mengatakan, pada dasarnya, JANGAN PERNAH menggunakan float atau double langsung sejak itu Anda akan terikat pada arsitektur prosesor (dan saya pikir JVM cepat diselesaikan tahun ini :)). Jadi primitif apa yang aman? int?
Dan Rosenstark
9
Saya tidak mengatakan TIDAK PERNAH menggunakan primitif secara langsung. Ada saat-saat primitif langsung dapat bermasalah, seperti jika variabel dapat digunakan untuk menyimpan data yang bisa meluap, seperti pada 64-bit. Secara umum, menggunakan typedef yang bergantung pada arsitektur lebih aman, karena kode itu cenderung meledak pada arsitektur yang berbeda. Namun, terkadang menggunakan tipe 32-bit bisa sepenuhnya aman dan menghemat memori Anda. Ukuran primitif mungkin kurang dari masalah dalam JVM, tetapi Obj-C dan C dikompilasi, dan mencampur 32 dan 64 bit perpustakaan dan kode memang bermasalah.
Quinn Taylor
1
@ QuinnTaylor dapatkah Anda memberikan contoh praktis tentang bagaimana float akan meluap sementara CGFloat tidak? Baik float dan CGFloat memiliki jumlah bit yang terbatas. Anda bisa meluap keduanya dengan perlu menyimpan lebih banyak bit daripada yang bisa mereka pegang.
Pwner
76

CGFloat adalah float reguler pada sistem 32-bit dan sistem 64-bit ganda

typedef float CGFloat;// 32-bit
typedef double CGFloat;// 64-bit

Jadi Anda tidak akan mendapatkan penalti kinerja.

Thomas Zoechling
sumber
3
Nah, Anda menggunakan memori dua kali lebih banyak, jika Anda khawatir dengan memori.
Tyler
8
Hanya pada 64-bit.
Quinn Taylor
13
Benar, iPhone OS adalah 32-bit. Jika dipikir-pikir, iPhone tidak mendorong batasan RAM 4GB 32-bit, juga tidak menggunakan prosesor Intel (yang 64-bit lebih cepat dari 32-bit). Plus, itu menggunakan Modern Runtime (bukan Legacy Runtime 32-bit pada desktop - cari SO untuk istilah-istilah ini jika Anda penasaran) sehingga pada dasarnya dapat melakukan semuanya 64-bit OS X dapat. Mungkin suatu hari nanti kita akan melihat perangkat yang menjalankan OS iPhone dan 64-bit, tetapi saat ini tidak ada.
Quinn Taylor
23
Masukkan: iPhone 5S
dgund
7
5S sekarang dalam 64 bit, terakhir kali saya memasuki konferensi (london), mereka mengatakan cara mereka menjalankan aplikasi 32-bit pada ios7 adalah dengan memasukkan kumpulan cache bersama lainnya dalam memori, yang dapat menghasilkan penggunaan lebih banyak memori secara keseluruhan. jadi nilainya untuk mengkonversi semuanya hingga 64-bit. (kecuali jika Anda ingin mendukung 5.1+ atau 6.0+)
phil88530
2

Seperti yang orang lain katakan, CGFloat adalah pelampung pada sistem 32-bit dan sistem ganda pada 64-bit. Namun, keputusan untuk melakukan itu diwarisi dari OS X, di mana ia dibuat berdasarkan karakteristik kinerja CPU PowerPC awal. Dengan kata lain, Anda seharusnya tidak berpikir bahwa float untuk CPU 32-bit dan ganda untuk CPU 64-bit. (Saya percaya, prosesor ARM Apple mampu memproses ganda jauh sebelum 64-bit.) Kinerja utama dari penggunaan ganda adalah bahwa mereka menggunakan memori dua kali lipat dan karenanya mungkin lebih lambat jika Anda melakukan banyak operasi floating point. .

pengguna3259383
sumber
2

Objektif-C

Dari kode sumber Foundation, dalam CoreGraphics ' CGBase.h:

/* Definition of `CGFLOAT_TYPE', `CGFLOAT_IS_DOUBLE', `CGFLOAT_MIN', and
   `CGFLOAT_MAX'. */

#if defined(__LP64__) && __LP64__
# define CGFLOAT_TYPE double
# define CGFLOAT_IS_DOUBLE 1
# define CGFLOAT_MIN DBL_MIN
# define CGFLOAT_MAX DBL_MAX
#else
# define CGFLOAT_TYPE float
# define CGFLOAT_IS_DOUBLE 0
# define CGFLOAT_MIN FLT_MIN
# define CGFLOAT_MAX FLT_MAX
#endif

/* Definition of the `CGFloat' type and `CGFLOAT_DEFINED'. */

typedef CGFLOAT_TYPE CGFloat;
#define CGFLOAT_DEFINED 1

Hak Cipta (c) 2000-2011 Apple Inc.

Ini pada dasarnya dilakukan:

#if defined(__LP64__) && __LP64__
typedef double CGFloat;
#else
typedef float CGFloat;
#endif

Di mana __LP64__menunjukkan apakah arsitektur saat ini * adalah 64-bit.

Perhatikan bahwa sistem 32-bit masih dapat menggunakan 64-bit double, hanya membutuhkan lebih banyak waktu prosesor, jadi CoreGraphics melakukan ini untuk keperluan optimasi, bukan untuk kompatibilitas. Jika Anda tidak khawatir tentang kinerja tetapi khawatir tentang akurasi, cukup gunakan double.

Cepat

Dalam Swift, CGFloatadalah structpembungkus baik Floatpada arsitektur 32-bit atau Doublepada yang 64-bit (Anda dapat mendeteksi ini saat run-atau compile-time dengan CGFloat.NativeType)

Dari kode sumber CoreGraphics, diCGFloat.swift.gyb :

public struct CGFloat {
#if arch(i386) || arch(arm)
  /// The native type used to store the CGFloat, which is Float on
  /// 32-bit architectures and Double on 64-bit architectures.
  public typealias NativeType = 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.
  public typealias NativeType = Double
#endif

* Khususnya, longs dan pointer, maka LP. Lihat juga: http://www.unix.org/version2/whatsnew/lp64_wp.html

Ben Leggiero
sumber
1

sebutkan saja - Jan, 2020 Xcode 11.3 / iOS13

Cepat 5

Dari kode sumber CoreGraphics

public struct CGFloat {
    /// 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
Boyan Jakimov
sumber