Kiat umum untuk mewakili jumlah besar

21

Kadang-kadang, saat bermain golf, seseorang harus mewakili sejumlah besar kode mereka. Menulisnya apa adanya dapat secara signifikan meningkatkan byte-count.

Apa 1 tips umum yang Anda miliki untuk mewakili angka panjang secara ringkas dalam kode?

Silakan kirim satu tip per jawaban.


1 Dengan umum , maksud saya tip yang dapat diterapkan ke lebih dari satu bahasa. Untuk kiat khusus bahasa, poskan di utas masing-masing.

Arjun
sumber
Terkait
Martin Ender
Saya melihat seseorang salah mengerti pertanyaan - mungkin judulnya seharusnya mengatakan ini tentang golf.
Ørjan Johansen
Juga terkait
Beta Decay

Jawaban:

15

Carilah nomor khusus

Beberapa bahasa memiliki fungsi bawaan untuk kuadrat, eksponensial dengan basis 2, perdana ke- n , faktorial, atau prosedur lain yang dapat menghasilkan angka besar. Periksa apakah nomor Anda termasuk dalam kategori mana pun.

Dan jika tidak, mungkin saja angka yang lebih besar cocok untuk keperluan Anda dan dapat digunakan sebagai gantinya.

Luis Mendo
sumber
4
Bahkan jika angka yang Anda inginkan tidak dapat dihasilkan dengan fungsi builtin, dimungkinkan untuk menghasilkan angka yang dapat Anda gunakan sebagai dasar perhitungan sederhana untuk sampai ke nomor Anda, sambil tetap menyimpan byte daripada menuliskannya.
Shaggy
7
+1 untuk "angka lebih besar" - jika 1.01e6iterasi sudah cukup, 1e7hemat 3 byte dengan mengorbankan waktu berjalan.
Chris H
13

Gunakan operator boolean bitwise

Beberapa bahasa memiliki bitwise AND, OR, XOR, dan kadang-kadang TIDAK.

Mengekspresikan angka besar tertentu sebagai kombinasi bitwise dari hasil eksponensial atau shift kiri dan nomor lain dapat membuat Anda tepat angka yang Anda butuhkan. Ini biasanya hanya sepadan jika jumlahnya menjadi cukup besar.

Sebagai contoh, 2147483722adalah 10 byte, tetapi 2<<30^74(2 ^ 31 bitwise-XORed dengan 74) hanya 8.

L3viathan
sumber
3
Operator shift dapat diganti dengan eksponensial, jika bahasa memiliki operator itu (mis bc.). Dan XOR tidak pernah lebih bermanfaat daripada +dan -: dalam hal ini, xor dan add memberikan hasil yang sama, tetapi dalam semua kasus ada beberapa integer yang dapat ditambahkan atau dikurangi untuk menghasilkan hasil yang sama seperti xor dengan integer, dan addend adalah tidak lebih besar dan terkadang lebih pendek.
rici
3
@rici Benar jika semua bilangan bulat ditulis sebagai desimal sederhana, tetapi mungkin saja bilangan bulat yang akan digunakan dengan xor dapat dipersingkat dengan cara bilangan bulat yang dapat digunakan dengan plus atau minus tidak dapat: pikirkan sesuatu seperti 1e9^2e9.
hvd
2
@rici Bagaimana Anda mengekspresikan 9<<49^7<<19menggunakan penambahan, bukan xor?
L3viathan
2
@rici Tidak, saya maksudkan apa yang saya tulis. Ini dievaluasi 1286561280dalam JavaScript dan Perl (dan mungkin bahasa lain), dan itu ekspresi yang lebih pendek untuk menghasilkan nilai itu daripada menggunakan +atau setara -.
hvd
@ DVD: OK, titik diambil.
rici
11

Gunakan String untuk angka berulang

Untuk bilangan yang sangat berulang, Anda bisa menggunakan string dan melemparkannya ke Integer. Misalnya, dalam JavaScript

+"1".repeat(100) // returns 100 1s (saves 84 bytes!)
Arjun
sumber
2
Atau Anda bisa menggunakan fraksi yang sangat besar, 1e100/9dalam hal ini.
ETHproduksi
11

Gunakan Notasi Ilmiah

Notasi ilmiah dapat menghemat byte jika nomor panjang. Sebagai contoh:

3564e-8 // returns 0.00003564 (saves 3 bytes!)
Arjun
sumber
3
Mengapa tidak digunakan saja 3564e-8dalam kasus itu?
Joey
@ Joey Ya, tentu saja! Terima kasih! :)
Arjun
Memang, Anda biasanya dapat menulis nomor lain sebagai .00003564, yang juga satu byte lebih pendek lagi.
Joey
@ Joey Tidak semua bahasa bisa, karenanya, saya tidak akan mengeditnya.
Arjun
Apakah disengaja bahwa 3564 (kiri) menjadi 354 (kanan) atau apakah itu salah ketik?
Erik
10

Cari nomor lain untuk digunakan

Ini mungkin terdengar seperti bukan jawaban, tetapi tidak selalu jelas bahwa angka yang lebih besar dapat dihitung dengan kode yang lebih pendek. Contoh yang saya ingat adalah Keluaran salinan googol dari string , di mana jawaban yang jelas membutuhkan komputasi 10 100 . Ternyata, menghitung kelipatan 10 100 mengarah ke jawaban yang sama benarnya, tetapi dalam beberapa bahasa, jawaban yang lebih pendek. Jawaban Dennis di sana menggunakan 100 100 , saya sendiri menggunakan 250 255 .

hvd
sumber
4
Contoh lain dari ini adalah CJam di mana Anda bisa mendapatkan cap waktu saat ini dengan esjika Anda hanya membutuhkan sejumlah besar tetapi tidak peduli nilainya (atau selalu sama).
Martin Ender
10

Kompresi Dasar

Kode dekompresi basis bisa sangat kompleks, tetapi jika Anda memiliki jumlah yang sangat besar kadang-kadang dapat membantu untuk mengompresnya di beberapa basis yang lebih tinggi dari 10.

Ini juga membantu bahwa dalam beberapa bahasa, kode kompresi dasar sangat sederhana. Sebagai contoh, PHP memiliki base64_decode(_), Python memiliki int(_,36), JavaScript parseInt(_,36), dan banyak bahasa golf memiliki built-in dekompresi dasar. Misalnya, dalam CJam:

"+ÜTbô±"256b

Ini mengandung yang tidak patut dicetak. Cobalah online!

Ini menghasilkan:

12345678987654321
Buah Esolanging
sumber
9

Gunakan pecahan eksponensial untuk angka berulang yang besar

Katakanlah Anda ingin menghasilkan angka yang terbuat dari 100 1. Anda dapat menggunakan int("1"*100),, +"1".repeat(100)dll. Tetapi Anda juga dapat memanfaatkan fakta bahwa itu sangat dekat

1e100/9

Ini bekerja paling baik untuk angka yang sangat berulang, seperti yang terbuat dari satu digit. Beberapa digit berulang juga bekerja dengan cukup baik:

12e100/99  // Generates 121212121212... (100 digits)

Kadang-kadang Anda akan menemukan beberapa pola aneh lainnya yang juga dapat direpresentasikan dengan cukup singkat dalam metode ini. Jika kebetulan Anda membutuhkan int("123456790"*11), misalnya:

1e100/81

Namun berhati-hatilah: angka-angka seperti int("1234567890"*10)tidak memiliki representasi yang mudah.

Produksi ETH
sumber
9

Gunakan Bitwise Left Shift untuk eksponensial 2

Meskipun, ada banyak bahasa yang mendukung operator untuk eksponensial, beberapa tidak. Dan yang tidak, biasanya memerlukan fungsi panggilan (atau metode Kelas / Objek), yang dapat menelan biaya beberapa byte.

Tetapi Anda dapat menghemat beberapa byte saat Anda perlu menaikkan 2 ke daya n dengan menggunakan operator Bitwise Left Shift <<sebagai 1<<n. Perhatikan bahwa ini hanya akan menghemat byte jika n lebih besar atau sama dengan 17. Namun, ini akan selalu menghemat byte jika n dinamis. Beberapa contoh:

1<<2 // returns 4 (3 bytes more :( )
1<<3 // returns 8 (3 bytes more :( )
1<<6 // returns 64 (2 bytes more :( )
1<<14 // returns 16384 (no bytes saved)
1<<17 // returns 131072 (saves 1 byte!)
1<<18 // returns 262114 (saves 1 byte!)
Arjun
sumber
4
Perhatikan bahwa Anda dapat menggunakan nilai-nilai lain alih-alih 1. 8<<9 // 4096sehingga kita dapat memperoleh hingga 99<<616 byte, yang sama dengan 6,917,529,027,641,081,856menghemat 13 byte!
Draco18s
@ Draco18s Ya, dan dibahas di sini .
Arjun
Yang satu lagi mencakup operator bitwise boolean. Ya, ia memiliki bithifting juga, tetapi ini berbicara tentang menggunakan dua angka besar untuk XOR dan mendapatkan nomor ketiga spesifik.
Draco18s
7

Teorema Sisa Tiongkok

Jika bilangan bulat besar yang sewenang-wenang sering muncul, atau representasi bilangan bulat besar dalam bahasa pemrograman target menghabiskan terlalu banyak byte, Anda dapat mempertimbangkan menggunakan Teorema Sisa Bahasa Cina.

Pilih beberapa bilangan bulat relatif prima m i > = 2, dan Anda dapat mengekspresikan angka besar dari 0 hingga lcm (m 1 , m 2 , ..., m i ) -1

Misalnya, saya memilih 2, 3, 5, 11, 79, 83, 89, 97, maka saya dapat mengungkapkan angka kurang dari 18680171730 secara unik. 10000000000 (1e10) dapat dinyatakan sebagai 0,1,0,1,38,59,50,49 (1e10 mod 2, 3 ..., 97) yang tidak perlu dinyatakan sebagai kelas / struct Big Integer khusus yang mungkin menghemat beberapa byte dalam beberapa bahasa pemrograman.

Penambahan dan substraksi dapat dilakukan secara langsung menggunakan representasi ini. Contoh:

(0,1,0,1,38,59,50,49)+(0,2,0,6,23,20,16,53) = 1e10 + 5000 
                                            = (0+0 mod 2, 1+2 mod 3, 0+0 mod 5, 1+6 mod 11, 38+23 mod 79, 59+20 mod 83, 50+16 mod 89, 49+53 mod 97)
Aria Ax
sumber
1
Mau uraikan hal itu?
Skidsdev
@ Mayube Saya telah menambahkan beberapa penjelasan, tapi saya ragu itu tidak berguna dalam banyak kasus.
Aria Axe
1
Ini "teorema sisa".
Ørjan Johansen
6

Gunakan String Padding (jika memungkinkan)

Jika sejumlah besar menyertakan digit berulang di awal atau akhir, Anda mungkin dapat menyimpan byte dengan menggunakan salah satu metode padding bahasa Anda untuk membangun string nomor yang Anda cari, yang kemudian dapat Anda konversi menjadi bilangan bulat.


Contoh

Untuk menghasilkan angka 1111111111111111111111112(25 byte) dalam JavaScript (ES8):

+"2".padStart(25,1) // 19 bytes
Shaggy
sumber
3

Gunakan Eksponen

Jika bahasa Anda memiliki operator eksponen, Anda mungkin dapat menggunakannya untuk menghasilkan, jika bukan angka yang Anda inginkan, setidaknya angka yang dapat Anda lakukan dengan perhitungan sederhana atau 2 angka untuk sampai pada nomor Anda. Bahkan tanpa operator, Anda mungkin masih bisa menyimpan byte dengan fungsi atau metode bawaan.

Contoh

The bilangan bulat aman maksimum dalam JavaScript adalah 9007199254740991, yang merupakan 16 digit. Dalam ES7, ini dapat dihitung dengan 7 byte berikut:

2**53-1

Persamaan dalam ES6 dan sebelumnya, sementara panjang yang sama dengan bilangan bulat itu sendiri dalam contoh ini, menunjukkan bahwa menggunakan metode yang lebih verbose mungkin tidak perlu biaya byte.

Math.pow(2,53)-1

Meskipun demikian, hal di atas dapat bekerja lebih pendek jika, misalnya, Anda telah memiliki Mathalias karakter tunggal di tempat lain dalam kode Anda.

Shaggy
sumber
2

Gunakan pecahan sebagai pengganti float

Contoh: 1./3sebagai pengganti0.333333333

RosLuP
sumber