Bagaimana game idle menangani jumlah besar seperti itu?

31

Hanya ingin tahu bagaimana game seperti Tit tit dan Cookie Clicker menangani jumlah besar seperti itu.

Saya mencoba menerapkan game idle namun format angka terbesar yang didukung oleh C # adalah desimal.

Saya ingin mendukung hingga 10 ^ 500; yang perlu floating point

Bagaimana saya bisa menangani ini?

PS itu harus lintas platform yaitu pc, mac, ios, android dan kompatibel dengan Unity

MathHelp
sumber
2
Jika saya ingat dengan benar, Anda memiliki akses ke kode Cookie Clicker, jadi Anda bisa memeriksanya ...
Vaillancourt
Tidak, saya sudah memblokir Cookie Clicker dari pikiran saya!
Arturo Torres Sánchez
2
Saya telah melihat sumber yang telah dikompilasi untuk TimeClickers , sebuah game Unity. Mereka hanya menggunakan double. Jika itu saya, saya akan menggunakan BigInteger .
BlueRaja - Danny Pflughoeft
1
@VioletGiraffe: Saya agak setuju, dan saya ingin membuat (keraguan?) Keraguan saya (untuk membantu OP membuat pertanyaan menjadi lebih jelas): Apa itu "permainan idle" sehubungan dengan pertanyaan (yang membuat jenis ini permainan kasus khusus untuk jumlah besar)? Jenis angka apa yang dimaksud dengan " angka besar seperti itu " (sorot sendiri)? Seberapa besar angka yang Anda inginkan?
ATAU Mapper
Anda selalu dapat menyimpan sejumlah besar dalam string dan dengan mudah mengimplementasikan fungsi untuk melakukan penjumlahan pada string.
dev-masih

Jawaban:

40

Jika Anda hanya ingin menyimpan angka besar tanpa akurasi lengkap, misalnya jika Anda akan menunjukkan 12.567.000.000.000 sebagai 12.567T (triliun), Anda bisa menggunakan float standar / nilai desimal dan menunjukkan angka x pertama yang signifikan, dengan akhiran yang cocok seperti ini. Ketika Anda berada di octillions, apakah Anda benar-benar perlu peduli dengan setiap kenaikan integer individu?

Ross Taylor-Turner
sumber
4
Ini mungkin jawaban yang paling masuk akal, dan saya cukup yakin Cookie Clicker hanya menggunakan pelampung standar dalam JavaScript - contohnya ketika saya "meretasnya" (baca: mengacaukan konsol) dan ketika jumlahnya mencapai 1e308 itu melonjak untuk "Infinity" dan saya dapat melanjutkan untuk membeli apa pun yang saya inginkan XD
Niet the Dark Absol
1
Besar! Fakta bahwa teks melompat ke "Infinity" terasa seperti pengembang defensif pengkodean di sekitar kemungkinan ini juga. Juga, kesederhanaan adalah raja.
Ross Taylor-Turner
19
@RossTurner - Mungkin tidak ada pengkodean yang terlibat dalam membuatnya menampilkan teks "Infinity" - infinity hanyalah nilai yang bisa dimiliki oleh float, dan JavaScript tahu cara menampilkannya, seperti halnya banyak bahasa lain.
Jibb Smart
Pelampung standar (presisi ganda, 8 byte) tidak akan memungkinkan untuk merepresentasikan angka hingga 10 ^ 500 seperti yang dipersyaratkan pertanyaan awal, ia akan naik hingga ~ 10 ^ 300. Jika itu tidak cukup, kita harus menggunakan pelampung presisi quad yang mungkin tidak trivial tergantung pada bahasanya.
Peteris
1
Apa yang harus diketahui oleh setiap programmer tentang angka floating point: floating-point-gui.de
Steve
20

Anda dapat menggunakan sesuatu seperti BigInteger , yang hanya tersedia di .net 4.0 jika saya tidak salah (tidak didukung oleh semua platform build unity).

Ada beberapa pustaka yang berupaya menghadirkan fungsionalitas ini tanpa persyaratan .net4.0. Sebagai contoh di sini .

Atau, Anda dapat menggunakan angka yang lebih kecil untuk mewakili yang lebih besar, dengan melacak pengali. Sebagai contoh:

double value = 9;
enum Multiplier {
   Hundred,
   Thousand,
   Million,
   Billion,
   Trillion
}

Sekarang, meskipun Anda memiliki nilai 9, jika Anda memasangkannya dengan pengganda Anda, Anda dapat secara efektif menyatakan bahwa 9 sebagai 9 triliun (Entah dengan memasukkan "triliun" atau menulis sesuatu yang akan menambahkan nol pada akhir nilai Anda. ).

jallan
sumber
Perlu dicatat bahwa kelas-kelas seperti BigIntegermenggunakan representasi String atau Byte [] dari angka - jadi pada dasarnya orang dapat membuat kelas mereka sendiri yang hanya menambah dan mengurangi dua "angka sebagai Strings atau Bytes" - ( biasanya jenis permainan ini tidak tidak membutuhkannya tetapi Anda dapat mendukung perkalian atau pembagian atau fungsi yang lebih canggih lainnya ) - tetapi mereka harus ingat bahwa selalu ada batas fisik di mana mereka mungkin kehabisan memori.
DoubleDouble
1
Setiap byte mengalikan ukuran nomor Anda dengan 256. Jika Anda kehabisan memori mencoba mewakili suatu angka, nomor Anda toh tidak memiliki nilai sebenarnya. 256 ^ (2 miliar) = 2 ^ 8 ^ (2 miliar) = 2 ^ (16 miliar) ~ = 10 ^ (5 miliar) (wolframalpha gagal mencoba melakukan konversi terakhir). Anda dapat menentukan volume Planck individual di alam semesta yang dapat diamati menggunakan seperti 150 digit (<500 bit).
MichaelS
11

Anda mungkin perlu menulis kelas Anda sendiri untuk digunakan di Unity, tetapi itu tidak terlalu sulit.

Secara internal, ini bisa berupa daftar bilangan bulat (seperti a List<int>), dengan setiap elemen dalam daftar terkait dengan grup yang terdiri dari 9 digit. Setiap bilangan bulat akan memiliki kisaran 0 hingga 999 999 999. Bilangan bulat dapat mendukung sedikit di atas 2 miliar, dan menggandakannya jika itu tidak ditandatangani, tetapi Anda ingin setiap "digit" meluap 1 000 000 000, karena Anda juga ingin untuk dapat dengan mudah mengkonversi angka besar Anda menjadi string untuk tampilan. Lebih mudah untuk menggabungkan apa yang sudah digit desimal ( return group[i].ToString() + group[i-1].ToString() and so on) daripada mencari tahu cara menampilkan jumlah grup yang berada di luar kisaran jenis data biasa.

Jadi, int pertama dalam daftar Anda akan mewakili 1s. Yang berikutnya adalah jumlah miliaran. Berikutnya, jumlah segi empat, dan sebagainya.

Penambahan dan pengurangan akan berfungsi seperti halnya penambahan dan pengurangan pena-dan-kertas, di mana Anda harus menonton untuk meluap dan membawanya ke "digit" berikutnya, tetapi alih-alih angka dengan rentang 0-9, angka Anda berkisar dari 0 hingga 999 999 999.

Jibb Smart
sumber
10

Untuk menangani angka besar, saya akan melihat apa yang saya pikir adalah contoh yang baik seperti Tower of Hero . Pojok kiri atas:

1

2
(sumber: mzstatic.com )

Tanpa masuk ke permainan, cara menangani angka relatif sederhana: Anda melihat dua ember angka. Saat Anda semakin tinggi di menara, dan menghasilkan lebih banyak "emas", kedua ember itu hanya mewakili angka yang lebih besar.

120 
120M320K - 120 Million
120B631M - 120 Billion
120T134B - 120 Trillion

Setelah permainan berlalu, T itu bergerak menjadi a, b, c ... z, aa, ab, ...

56aa608z

Melakukannya dengan cara ini, masih memungkinkan Anda mengetahui berapa banyak emas yang telah Anda "dapatkan" ... sambil tidak menghalangi permainan secara detail.

Apakah Anda benar-benar peduli tentang Jutaan ketika nomor Anda melebihi Triliun?

Apakah itu menyimpan nomor dalam Int, Big Int, Float, Double, Desimal, ...? Array Ubahsuaian? Saat Anda menangani angka dengan cara "tidak jelas", saya pikir itu tidak penting ...

Semua yang mungkin penting adalah bagian yang paling signifikan - dalam hal ini, 6 pertama ... Setelah itu, MUNGKIN 3 atau 6 berikutnya - karena penghasilan beberapa ratus K dapat terguling ke Jutaan - tetapi ada titik di mana penghasilan beberapa ratus K tidak akan mempengaruhi Anda ketika Anda menekan T ... apalagi aa dan seterusnya.

Jarak tempuh Anda akan bervariasi (tergantung pada apa yang Anda inginkan / butuhkan) ... Hanya berpikir saya akan mengeluarkan 2c saya pada apa yang saya pikir adalah contoh yang baik / sederhana.

Edit:

Pemikiran lebih lanjut tentang bagaimana saya akan menerapkan sistem penomoran: Saya akan memiliki nomor dengan 3 bagian penting: XXXX.YYY (...) xZZZ.

X is the most significant digits, 
Y trailing 
Z the multiplier (multiple of 3).

Jadi 120.365x1 akan menjadi 120k365 ... 120.365x2 akan menjadi 120M365K ... dll. Tekan 4 terdepan (1200.365x2), lalu putar angka 1.200365 (...) x3. Bam. Anda memiliki 1B200M.

XY akan cocok dengan mudah dalam Desimal atau Float ... dengan Z duduk di sebelahnya sebagai int / unsigned int.

Dengan pelampung, Anda akan dapat mempertahankan jumlah digit yang lumayan - tetapi semakin tidak penting - setelah titik.

Z akan dengan mudah mewakili blok angka yang mudah dimengerti:

K = 1
M = 2
B = 3
T = 4
a = 5 
...
z = 31 (I may be off on this)
aa = 32
...
az = 58
ba = 59
...
...
WernerCD
sumber
1

Dan cara mudah untuk menangani jumlah besar adalah dengan memiliki lebih dari satu nilai INTEGER kemudian BAWA overflow apa pun. Jika Anda memiliki nilai INT 16-Bit (0 hingga 65535) dan Anda ingin memiliki lebih dari itu, gunakan dua nilai INT 16-bit dalam satu baris. Anggap saja seperti memiliki nilai BYTE (0 hingga 255) tetapi hanya menggunakannya hingga 99 digit nilai. Setelah mencapai 100, kemudian gulung ke nilai BYTE berikutnya yang lebih tinggi untuk sebanyak digit yang Anda anggap berguna. Dengan komputer GHZ saat ini, bahkan pengkodean yang ceroboh seperti itu tidak masalah.

Tentu saja, ada alternatif yang sedikit lebih cepat.
Jika Anda menambahkan 18 berulang kali ke angka, lebih cepat untuk hanya mengurangi 2 dan menambahkan 20. 18, 36, 54, 72, 90, 108, ... 18 = 20 + (- 2).
Ia bekerja di Binary juga. (Nilai desimal yang sama dalam Biner) 10010, 100100, 110110, 1001000
DEC (18) = BIN (10010)
Kecuali untuk penguraian Biner yang lebih mudah, Anda perlu memikirkan 18 = 16 + 2
DEC (16 + 2) = BIN (10000 + 00010). Jika nilainya 15, maka anggap sebagai menambahkan 16 dalam biner dan mengurangi 1 (10000-00001).

Dengan cara ini, Anda dapat menjaga potongan angka ke batas yang dapat dikelola per nilai.
Jika Anda menggunakan metode pengkodean ceroboh yang membatasi nilai INT 16-bit dasar (0 hingga 65535) hingga batas desimal 4 digit (0 hingga 9999) maka yang harus Anda lakukan adalah ketika nilainya melebihi batas 9999, kurangi 9999 darinya dan bawa ke chunk nilai berikutnya (karena pada dasarnya Anda melakukan "tambah & subs" dengan angka versus perhitungan biner sungguhan).

Idealnya, Anda hanya perlu MATEMATIKA SIMMBOL yang Anda pelajari di sekolah dasar. Bagaimana cara kerjanya? Jika Anda memiliki simbol desimal 1 dan Anda menambahkannya ke 1 maka Anda mendapatkan simbol desimal 2. Alasan saya menyebutnya simbol adalah karena Anda bisa menggunakan seri simbol apa saja dengan tabel pencarian "IF simbol X (1) ditambahkan ke simbol X (4) LALU simbol keluaran X (5) ". Simbol X (1) bisa menjadi gambar kucing dan simbol X (4) bisa menjadi tanda PERSEN, tetapi tidak masalah. Anda memiliki simbol, buku aturan dasar tentang apa yang terjadi kemudian simbol tersebut digabungkan (seperti tabel perkalian yang Anda hafal sewaktu kecil) dan simbol apa yang harus dihasilkan sebagai bagian dari operasi itu. Dengan menggunakan Matematika Simbolik Anda dapat menambahkan jumlah digit tanpa batas tanpa pernah benar-benar memanggil batas numerik prosesor Anda.

Salah satu cara untuk melakukan ini dalam pengkodean yang mudah adalah memiliki masing-masing angka yang diwakili Anda ingin bekerja dengan sebagai unit tunggal dalam array berdimensi besar. Jika Anda ingin merepresentasikan 4096 angka desimal (tidak melebihi 2 digit per kotak unit), maka Anda mengalokasikan 2 set 4096 lokasi array BYTE. Menyimpan nilai 1098874 akan menggunakan array sebagai (1) (0) (9) (8) (8) (7) (4). Jika Anda menambahkan nilai 7756 ke dalamnya, Anda akan mengubahnya menjadi (7) (7) (5) (6) dan kemudian menambahkan. Hasilnya adalah (1) (0) (9) (15) (15) (12) (10) yang kemudian akan Anda kurangi shift kanan-ke-kiri sampai semua kotak digit dinormalisasi menjadi nilai (0 hingga 9). Nilai paling kanan (10) akan memiliki 10 dikurangi dan nilai yang dihasilkan akan menjadi nol (0) dan itu akan membawa nilai (1) ke kotak kiri-depan (12) untuk membuatnya (13) yang kemudian akan memiliki 10 dikurangi untuk membuatnya menjadi (3).

Kemacetan
sumber
7
-1 untuk TERLALU BANYAK KUNING
Slipp D. Thompson
5
Hei @Glocklock, saya baru sadar bahwa Anda adalah pengguna yang sepenuhnya baru— selamat datang. Saya harus mengklarifikasi bahwa downvote saya tidak permanen; itu dimaksudkan sebagai kritik yang membangun. Ada nilai untuk jawaban yang Anda berikan, dan saya akan dengan senang hati mengubahnya menjadi suara positif setelah Anda membuat koreksi yang saya minta. Juga, perlu diingat bahwa SE bukan forum; jawaban yang baik tidak dibaca dan kemudian dilupakan tetapi membayar dividen perwakilan dari waktu ke waktu. Merevisi jawaban Anda di sana-sini membantu komunitas dan perwakilan Anda. Saya harap saya tidak menakuti Anda; sekali lagi, selamat datang dan saya harap Anda akan menggunakan saran saya.
Slipp D. Thompson
1
Satu saran lain yang akan saya tawarkan adalah menggunakan beberapa format Markdown dasar, bukan all-caps. Membungkus teks dengan backticks ( `text`text) akan membuatnya menjadi satu spasi, sesuai untuk potongan kode, nama fungsi, data, dll. Membungkus teks dalam garis bawah atau tanda bintang akan membuatnya miring ( _text_atau *text*teks ), dan menggarisbawahi atau menggandakan ganda- tanda bintang akan membuatnya tebal ( __text__atau **text**teks ).
Slipp D. Thompson
0

Apa yang Anda lakukan adalah memiliki beberapa variabel yang digabungkan, dan kemudian Anda mengontrol penambahan dan melimpah di antara mereka sendiri. Anda dapat memiliki angka berapa pun dengan cara itu. Gabungkan 10.000 bilangan bulat 32-bit, dan Anda memiliki angka dengan 32.000 bit, jika itu yang Anda butuhkan. Tidak ada batasan dalam bahasa pemrograman apa pun. Satu-satunya batasan adalah apa yang dapat Anda temukan.

jujur
sumber
Bagi mereka yang memberikan suara, bisakah Anda menjelaskan mengapa? Bahkan jika ini bukan solusi yang populer, atau yang membutuhkan upaya nol, itu masih solusi, dan yang dapat memungkinkan Anda untuk melakukan hal yang sama bahkan pada bahasa / platform yang tidak mendukung doubleatau BigInteger.
TomTsagk