Suggerimenti generali per la rappresentazione di grandi numeri


21

A volte, mentre si gioca a golf, è necessario rappresentare un gran numero nel proprio codice. Scriverli così come sono può aumentare significativamente il conteggio dei byte.

Quali suggerimenti generali 1 hai per rappresentare i numeri lunghi in modo conciso nel codice?

Si prega di inviare un suggerimento per risposta.


1 Con generale intendo suggerimenti che possono essere applicati a più di una singola lingua. Per suggerimenti specifici sulla lingua, pubblica nella rispettiva discussione.




Ho visto qualcuno fraintendere la domanda - forse il titolo dovrebbe dire che si tratta di golf.
Ørjan Johansen,

Risposte:


15

Cerca numeri speciali

Alcune lingue hanno funzioni incorporate per quadrati, esponenziazione con base 2, n -esima, fattoriale o altre procedure che possono generare grandi numeri. Controlla se il tuo numero sembra cadere in una di queste categorie.

E in caso contrario, può accadere che un numero maggiore che si adatta ai tuoi scopi e possa essere utilizzato invece.


4
Anche se il numero desiderato non può essere generato con una funzione incorporata, potrebbe essere possibile generare un numero che può essere utilizzato come base per un semplice calcolo per arrivare al tuo numero, risparmiando comunque byte sulla scrittura.
Shaggy,

7
+1 per "numero più grande" - se 1.01e6è sufficiente iterazioni, 1e7salva 3 byte a spese del tempo di esecuzione.
Chris H,

13

Usa operatori booleani bit a bit

Alcune lingue hanno AND bit a bit, OR, XOR e talvolta NOT.

Esprimere un numero grande specifico come una combinazione bit a bit di un risultato di esponenziazione o spostamento a sinistra e un altro numero può portarti esattamente al numero che ti serve. Questo di solito vale la pena solo se i numeri diventano abbastanza grandi.

Ad esempio, 2147483722è 10 byte, ma 2<<30^74(2 ^ 31 bit a bit XORed con 74) è solo 8 byte .


3
L'operatore di turno può essere sostituito con esponenziazione, se la lingua ha quell'operatore (ad es bc.). E XOR non è mai più utile di +e -: in questo caso, xor e add danno lo stesso risultato, ma in tutti i casi esiste un numero intero che può essere aggiunto o sottratto per produrre lo stesso risultato di xor con un numero intero e l'addend è non più grande e talvolta più corto.
rici,

3
@rici Vero se tutti i numeri interi sono scritti come semplici decimali, ma è possibile che il numero intero da utilizzare con xor possa essere abbreviato in modi in cui il numero intero da utilizzare con più o meno non può: pensare a qualcosa di simile 1e9^2e9.
hvd,

2
@rici Come esprimeresti 9<<49^7<<19usando l'addizione invece di xor?
L3viathan,

2
@rici No, intendevo quello che ho scritto. Valuta 1286561280in JavaScript e Perl (e probabilmente in altre lingue), ed è un'espressione più breve per produrre quel valore rispetto all'equivalente usando +o -.
hvd,

@hvd: OK, punto preso.
rici,

11

Usa le stringhe per i numeri ripetitivi

Per i numeri che sono molto ripetitivi in ​​natura, puoi usare le stringhe e lanciarle su Integer. Ad esempio, in JavaScript

+"1".repeat(100) // returns 100 1s (saves 84 bytes!)

2
Oppure potresti usare una frazione molto grande, 1e100/9in questo caso.
ETHproductions

11

Usa la notazione scientifica

La notazione scientifica può salvare byte in caso di numeri lunghi. Per esempio:

3564e-8 // returns 0.00003564 (saves 3 bytes!)

3
Perché non usare solo 3564e-8in quel caso?
Joey,

@Joey Sì, certo! Grazie! :)
Arjun,

Certo, di solito puoi scrivere l'altro numero come .00003564, che è anche di nuovo un byte più breve.
Joey,

@Joey Non tutte le lingue, quindi, non lo modificherò.
Arjun

È intenzionale che 3564 (a sinistra) diventi 354 (a destra) o è un errore di battitura?
Erik,

10

Cerca invece un altro numero da utilizzare

Può sembrare una non risposta, ma non è sempre ovvio che un numero più grande può essere calcolato con un codice più breve. Un esempio che ricordo è l' output di una copia googol di una stringa , in cui le risposte ovvie richiedono il calcolo di 10000 . A quanto pare, calcolare qualsiasi multiplo di 10 100 porta a una risposta altrettanto corretta, ma in alcune lingue, più breve. La risposta di Dennis usa 100 100 , i miei usano 250 255 .


4
Un altro esempio di questo è CJam dove puoi ottenere il timestamp corrente esse hai solo bisogno di un numero elevato ma non ti importa del suo valore (o che è sempre lo stesso).
Martin Ender,

10

Compressione di base

Il codice di decompressione di base può essere abbastanza complesso, ma se hai un numero davvero enorme a volte può aiutare a comprimerlo in una base superiore a 10.

Aiuta anche che in alcune lingue, il codice di compressione di base è molto semplice. Ad esempio, PHP ha base64_decode(_), Python ha int(_,36), JavaScript ha parseInt(_,36)e molti linguaggi del golf hanno built-in di decompressione di base. Ad esempio, in CJam:

"+ÜTbô±"256b

Questo contiene un non stampabile. Provalo online!

Questo produce:

12345678987654321

9

Usa le frazioni esponenziali per grandi numeri ripetitivi

Supponi di voler generare il numero composto da 100 1. Potresti usare int("1"*100), +"1".repeat(100)ecc. Ma puoi anche approfittare del fatto che è molto vicino

1e100/9

Funziona meglio con numeri molto ripetitivi, come quelli composti da una sola cifra. Anche un paio di cifre ripetute funzionano abbastanza bene:

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

Di tanto in tanto troverai qualche altro modello strano che può anche essere rappresentato abbastanza tersamente in questo metodo. Se ti è capitato di aver bisogno int("123456790"*11), ad esempio:

1e100/81

Attenzione però: numeri come int("1234567890"*10)non hanno una rappresentazione così facile.


9

Usa Bitwise Left Shift per l'espiazione di 2

Sebbene, ci siano molte lingue che supportano l'operatore per l'espiazione, alcune no. E quelli che non lo fanno, di solito richiedono funzioni di chiamata (o metodi Class / Object), che possono costare pochi byte.

Ma puoi salvare alcuni byte quando devi aumentare 2 alla potenza n usando l'operatore Bitwise Left Shift <<come 1<<n. Nota che questo ti salverà byte solo se n è maggiore o uguale a 17. Tuttavia, ti salverà sempre byte se n è dinamico. Alcuni esempi:

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!)

4
Nota che puoi usare altri valori invece di 1. 8<<9 // 4096così possiamo arrivare a 99<<616 byte, il che equivale a 6,917,529,027,641,081,856salvare 13 byte!
Draco18s,

@ Draco18s Sì, ed è coperto qui .
Arjun,

Quello in più copre gli operatori bit per bit booleani. Sì, ha anche il bit-shifting, ma si tratta di usare due numeri grandi per XOR e ottenere un terzo numero specifico.
Draco18s

7

Teorema del resto cinese

Se compaiono frequentemente numeri interi grandi arbitrari o la rappresentazione di numeri interi grandi nel linguaggio di programmazione di destinazione costa troppi byte, puoi prendere in considerazione l'uso del teorema del residuo cinese.

Scegli alcuni interi relativamente primi a coppie m i > = 2 e puoi esprimere un numero grande da 0 a mcm (m 1 , m 2 , ..., m i ) -1

Ad esempio, scelgo 2, 3, 5, 11, 79, 83, 89, 97, quindi posso esprimere un numero inferiore a 18680171730 in modo univoco. 10000000000 (1e10) possono essere espressi come 0,1,0,1,38,59,50,49 (1e10 mod 2, 3 ..., 97) che non devono essere espressi come speciali classi / strutture di Big Integer che potrebbero salvare alcuni byte in qualche linguaggio di programmazione.

Aggiunta e sottrazione possono essere fatte direttamente usando questa rappresentazione. Esempio:

(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)

1
Ti interessa approfondire?
Skidsdev,

@Mayube Ho aggiunto alcune spiegazioni, ma dubito che sia inutile nella maggior parte dei casi.
Aria Axe

1
È "teorema del resto".
Ørjan Johansen,

6

Usa l'imbottitura di stringhe (ove possibile)

Se un numero elevato include una cifra ripetuta all'inizio o alla fine, potresti essere in grado di salvare i byte utilizzando uno dei metodi di riempimento della tua lingua per costruire una stringa del numero che stai cercando, che puoi quindi convertire in un numero intero.


Esempio

Per generare il numero 1111111111111111111111112(25 byte) in JavaScript (ES8):

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

3

Usa esponenti

Se la tua lingua ha un operatore esponente potresti essere in grado di usarlo per generare, se non il numero desiderato, almeno un numero su cui puoi eseguire un semplice calcolo o 2 per arrivare al tuo numero. Anche senza un operatore, potresti comunque essere in grado di salvare byte con una funzione o un metodo integrati.

Esempio

Il numero intero massimo sicuro in JavaScript è 9007199254740991, che è lungo 16 cifre. In ES7, questo può essere calcolato con i seguenti 7 byte:

2**53-1

L'equivalente in ES6 e precedenti, mentre la stessa lunghezza dell'intero stesso in questa istanza, dimostra che l'utilizzo di un metodo più dettagliato potrebbe non comportare necessariamente il costo di alcun byte.

Math.pow(2,53)-1

Quanto sopra, tuttavia, potrebbe risultare più breve se, ad esempio, si è già Mathaliasati su un singolo carattere altrove nel codice.


2

Usa le frazioni al posto del galleggiante

Esempio: 1./3al posto di0.333333333

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.