Conseils généraux pour représenter de grands nombres

21

Parfois, en jouant au golf, il faut représenter un ou plusieurs grands nombres dans leur code. Les écrire tels quels peut augmenter considérablement le nombre d'octets.

Qu'est - ce que le général 1 conseils avez - vous pour représenter les nombres longs de façon concise dans le code?

Veuillez poster un pourboire par réponse.


1 Avec générale , je veux dire des conseils qui peuvent être appliquées à plus d'une seule langue. Pour des conseils spécifiques à la langue, publiez dans leur fil respectif.

Arjun
la source
En relation.
Martin Ender
J'ai vu quelqu'un mal comprendre la question - le titre devrait peut-être dire qu'il s'agit de golf.
Ørjan Johansen

Réponses:

15

Attention aux numéros spéciaux

Certaines langues ont des fonctions intégrées pour les places, exponentiation avec la base 2, n premier -ème, factoriel, ou d' autres procédures qui peuvent générer un grand nombre. Vérifiez si votre numéro appartient à l'une de ces catégories.

Et si ce n'est pas le cas, il peut arriver qu'un plus grand nombre qui convient à vos besoins et puisse être utilisé à la place.

Luis Mendo
la source
4
Même si le nombre souhaité ne peut pas être généré avec une fonction intégrée, il peut être possible de générer un nombre que vous pouvez utiliser comme base pour un calcul simple pour arriver à votre numéro, tout en économisant des octets lors de l'écriture.
Shaggy
7
+1 pour "plus grand nombre" - si les 1.01e6itérations sont suffisantes, 1e7économise 3 octets au détriment du temps d'exécution.
Chris H
13

Utiliser des opérateurs booléens au niveau du bit

Certaines langues ont des bits ET, OU, XOR et parfois NON.

Exprimer un grand nombre spécifique sous la forme d'une combinaison au niveau du bit du résultat d'une exponentiation ou d'un décalage à gauche et d'un autre nombre peut vous aider à atteindre précisément le nombre dont vous avez besoin. Cela ne vaut généralement la peine que si les chiffres deviennent assez élevés.

Par exemple, 2147483722est de 10 octets, mais 2<<30^74(2 ^ 31 XOR au niveau du bit avec 74) n'est que de 8.

L3viathan
la source
3
L'opérateur de décalage peut être remplacé par l'exponentiation, si la langue a cet opérateur (par exemple bc). Et XOR n'est jamais plus utile que +et -: dans ce cas, xor et add donnent le même résultat, mais dans tous les cas il y a un entier qui peut être ajouté ou soustrait pour produire le même résultat que xor avec un entier, et l'addend est pas plus grand et parfois plus court.
rici
3
@rici True si tous les entiers sont écrits sous forme de décimales simples, mais il est tout simplement possible que l'entier à utiliser avec xor puisse être raccourci de manière que l'entier à utiliser avec plus ou moins ne puisse pas: penser à quelque chose comme 1e9^2e9.
hvd
2
@rici Comment exprimeriez-vous en 9<<49^7<<19utilisant l'addition au lieu de xor?
L3viathan
2
@rici Non, je voulais dire ce que j'ai écrit. Il évalue 1286561280en JavaScript et Perl (et probablement dans d'autres langages), et c'est une expression plus courte pour produire cette valeur que l'équivalent en utilisant +ou -.
hvd
@hvd: OK, point pris.
rici
11

Utilisez des chaînes pour les nombres répétitifs

Pour les nombres de nature très répétitive, vous pouvez utiliser des chaînes et les convertir en nombre entier. Par exemple, en JavaScript

+"1".repeat(100) // returns 100 1s (saves 84 bytes!)
Arjun
la source
2
Ou vous pouvez utiliser une très grande fraction, 1e100/9dans ce cas.
ETHproductions
11

Utiliser la notation scientifique

La notation scientifique peut économiser des octets en cas de nombres longs. Par exemple:

3564e-8 // returns 0.00003564 (saves 3 bytes!)
Arjun
la source
3
Pourquoi ne pas simplement l'utiliser 3564e-8dans ce cas?
Joey
@Joey Oui, bien sûr! Merci! :)
Arjun
Certes, vous pouvez généralement écrire l'autre nombre sous la forme .00003564, qui est également un octet plus court à nouveau.
Joey
@Joey Toutes les langues ne le font pas, donc je ne le modifierai pas.
Arjun
Est-ce intentionnel que 3564 (à gauche) devienne 354 (à droite) ou est-ce une faute de frappe?
Erik
10

Recherchez un autre numéro à utiliser à la place

Cela peut sembler une non-réponse, mais il n'est pas toujours évident qu'un plus grand nombre peut être calculé par un code plus court. Un exemple dont je me souviens est Output a googol copies of a string , où les réponses évidentes nécessitent le calcul de 10 100 . Il s'avère que le calcul d'un multiple de 10 100 conduit à une réponse tout aussi correcte, mais dans certaines langues, plus courte. La réponse de Dennis utilise 100 100 , la mienne utilise 250 255 .

hvd
la source
4
Un autre exemple de ceci est CJam où vous pouvez obtenir l'horodatage actuel avec essi vous avez juste besoin d'un grand nombre mais ne vous souciez pas de sa valeur (ou que c'est toujours la même chose).
Martin Ender
10

Compression de base

Le code de décompression de base peut être assez complexe, mais si vous avez un nombre vraiment énorme, cela peut parfois aider à le compresser dans une base supérieure à 10.

Il est également utile que dans certaines langues, le code de compression de base soit très simple. Par exemple, PHP a base64_decode(_), Python a int(_,36), JavaScript a parseInt(_,36), et de nombreux langages de golf ont des commandes de décompression de base. Par exemple, dans CJam:

"+ÜTbô±"256b

Cela contient un non imprimable. Essayez-le en ligne!

Cela donne:

12345678987654321
Esolanging Fruit
la source
9

Utilisez des fractions exponentielles pour les grands nombres répétitifs

Supposons que vous vouliez générer le nombre composé de 100 1. Vous pouvez utiliser int("1"*100), +"1".repeat(100)etc., mais vous pouvez également profiter du fait qu'il est très proche de

1e100/9

Cela fonctionne mieux pour les nombres très répétitifs, tels que ceux composés d'un seul chiffre. Quelques chiffres répétés fonctionnent également assez bien:

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

Parfois, vous trouverez un autre motif étrange qui peut également être représenté assez sommairement dans cette méthode. Si vous aviez besoin int("123456790"*11), par exemple:

1e100/81

Attention cependant: les nombres comme ceux-ci int("1234567890"*10)n'ont pas une représentation aussi simple.

ETHproductions
la source
9

Utilisez Bitwise Left Shift pour l'exponentiation de 2

Bien qu'il existe de nombreuses langues qui prennent en charge l'opérateur pour l'exponentiation, certaines ne le font pas. Et celles qui ne le nécessitent pas nécessitent généralement des fonctions d'appel (ou des méthodes Class / Object), qui peuvent coûter quelques octets.

Mais vous pouvez enregistrer quelques octets lorsque vous devez augmenter 2 à la puissance n en utilisant l'opérateur de décalage à gauche Bit <<as 1<<n. Notez que cela ne vous fera économiser des octets que si n est supérieur ou égal à 17. Cependant, cela vous fera toujours économiser des octets si n est dynamique. Quelques exemples:

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
la source
4
Notez que vous pouvez utiliser d'autres valeurs au lieu de 1. 8<<9 // 4096afin que nous puissions obtenir jusqu'à 99<<616 octets, ce qui équivaut à 6,917,529,027,641,081,856économiser 13 octets!
Draco18s
@ Draco18s Oui, et c'est couvert ici .
Arjun
Celui-ci couvre les opérateurs booléens au niveau du bit. Oui, il a aussi le décalage de bits, mais il s'agit d'utiliser deux grands nombres pour XOR et d'obtenir un troisième nombre spécifique.
Draco18s
7

Théorème du reste chinois

Si de grands nombres entiers arbitraires apparaissent fréquemment, ou si la représentation de grands nombres entiers dans le langage de programmation cible coûte trop d'octets, vous pouvez envisager d'utiliser le théorème du reste chinois.

Choisissez quelques entiers relativement premiers m i > = 2, et vous pouvez exprimer un grand nombre de 0 à lcm (m 1 , m 2 , ..., m i ) -1

Par exemple, je choisis 2, 3, 5, 11, 79, 83, 89, 97, puis je peux exprimer le nombre inférieur à 18680171730 uniquement. 10000000000 (1e10) peut être exprimé comme 0,1,0,1,38,59,50,49 (1e10 mod 2, 3 ..., 97) qui ne doivent pas être exprimés en tant que classe / structure spéciale Big Integer qui pourrait sauver quelques octets dans un langage de programmation.

L'addition et la soustraction peuvent être effectuées directement à l'aide de cette représentation. Exemple:

(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 Axe
la source
1
Voulez-vous élaborer sur ce point?
Skidsdev
@Mayube J'ai ajouté quelques explications, mais je doute que ce soit inutile dans la plupart des cas.
Aria Axe
1
C'est le "théorème du reste".
Ørjan Johansen
6

Utilisez un remplissage de chaîne (si possible)

Si un grand nombre comprend un chiffre répétitif au début ou à la fin, vous pourrez peut-être enregistrer des octets en utilisant l'une des méthodes de remplissage de votre langue pour construire une chaîne du nombre que vous recherchez, que vous pouvez ensuite convertir en entier.


Exemple

Pour générer le nombre 1111111111111111111111112(25 octets) en JavaScript (ES8):

+"2".padStart(25,1) // 19 bytes
Hirsute
la source
3

Utiliser des exposants

Si votre langue a un opérateur exposant, vous pourriez être en mesure de l'utiliser pour générer, sinon le nombre que vous voulez, au moins un nombre, vous pouvez effectuer un calcul simple ou 2 pour arriver à votre numéro. Même sans opérateur, vous pouvez toujours enregistrer des octets avec une fonction ou une méthode intégrée.

Exemple

Le nombre entier en toute sécurité maximum JavaScript est 9007199254740991, qui est de 16 chiffres. Dans ES7, cela peut être calculé avec les 7 octets suivants:

2**53-1

L'équivalent dans ES6 et les versions antérieures, bien qu'il ait la même longueur que l'entier lui-même dans cette instance, montre que l'utilisation d'une méthode plus détaillée ne vous coûtera pas nécessairement des octets.

Math.pow(2,53)-1

Ce qui précède, cependant, peut fonctionner plus court si, par exemple, vous avez déjà un Mathalias pour un seul caractère ailleurs dans votre code.

Hirsute
la source
2

Utilisez des fractions à la place du flotteur

Exemple: 1./3à la place de0.333333333

RosLuP
la source