Consejos generales para representar grandes números

21

A veces, mientras juega al golf, uno necesita representar un gran número en su código. Escribirlos tal cual puede aumentar significativamente el conteo de bytes.

¿Qué consejos generales 1 tiene para representar números largos de forma concisa en el código?

Por favor, publique un consejo por respuesta.


1 Con general , me refiero a consejos que se pueden aplicar a más de un idioma. Para consejos específicos del idioma, publique en su respectivo hilo.

Arjun
fuente
Relacionado.
Martin Ender
Vi a alguien malinterpretar la pregunta, tal vez el título debería decir que se trata de golf.
Ørjan Johansen

Respuestas:

15

Esté atento a los números especiales.

Algunas lenguas han incorporado funciones de plazas, la exponenciación con base 2, n primer -ésimo, factorial, u otros procedimientos que pueden generar grandes cantidades. Verifique si su número cae en alguna de esas categorías.

Y si no es así, puede suceder que un número mayor que se ajuste a sus propósitos y se pueda usar en su lugar.

Luis Mendo
fuente
44
Incluso si el número que desea no se puede generar con una función incorporada, puede ser posible generar un número que puede usar como base para un cálculo simple para llegar a su número, al tiempo que se ahorran bytes al escribirlo.
Shaggy
77
+1 para "número mayor": si las 1.01e6iteraciones son suficientes, 1e7ahorra 3 bytes a expensas del tiempo de ejecución.
Chris H
13

Usar operadores booleanos bit a bit

Algunos idiomas tienen bit a bit AND, OR, XOR y, a veces, NOT.

Expresar un número grande específico como una combinación bit a bit de un resultado de una exponenciación o desplazamiento a la izquierda y otro número puede llevarlo exactamente al número que necesita. Por lo general, esto solo vale la pena si los números se vuelven bastante grandes.

Por ejemplo, 2147483722es de 10 bytes, pero 2<<30^74(2 ^ 31 bit-XORed con 74) es solo 8.

L3viatán
fuente
3
El operador de desplazamiento se puede reemplazar con exponenciación, si el idioma tiene ese operador (por ejemplo bc) Y XOR nunca es más útil que +y -: en este caso, xor y add dan el mismo resultado, pero en todos los casos hay algún número entero que se puede sumar o restar para producir el mismo resultado que xor con un número entero, y el sumando es no más grande y a veces más corto.
rici
3
@rici Verdadero si todos los enteros se escriben como decimales simples, pero es posible que el entero que se usa con xor se acorte de manera que el entero que se usa con más o menos no puede: piense en algo así 1e9^2e9.
hvd
2
@rici ¿Cómo expresarías el 9<<49^7<<19uso de la suma en lugar de xor?
L3viathan
2
@rici No, quise decir lo que escribí. Se evalúa 1286561280en JavaScript y Perl (y probablemente en otros idiomas), y es una expresión más corta para producir ese valor que el equivalente usando +o -.
hvd
@hvd: OK, punto tomado.
rici
11

Use cadenas para números repetitivos

Para los números que son de naturaleza muy repetitiva, puede usar cadenas y convertirlos a entero. Por ejemplo, en JavaScript

+"1".repeat(100) // returns 100 1s (saves 84 bytes!)
Arjun
fuente
2
O podría usar una fracción muy grande, 1e100/9en este caso.
ETHproductions
11

Usar notación científica

La notación científica puede guardar bytes en caso de números largos. Por ejemplo:

3564e-8 // returns 0.00003564 (saves 3 bytes!)
Arjun
fuente
3
¿Por qué no solo usar 3564e-8en ese caso?
Joey
@Joey ¡Sí, por supuesto! ¡Gracias! :)
Arjun
Por supuesto, generalmente puede escribir el otro número como .00003564, que también es un byte más corto nuevamente.
Joey
@Joey No todos los idiomas lo hacen, por lo tanto, no editaré eso.
Arjun
¿Es intencional que 3564 (izquierda) se convierta en 354 (derecha) o es un error tipográfico?
Erik
10

Busque otro número para usar en su lugar

Esto puede parecer una falta de respuesta, pero no siempre es obvio que se pueda calcular un número mayor mediante un código más corto. Un ejemplo que recuerdo es la salida de una copia googol de una cadena , donde las respuestas obvias requieren calcular 10 100 . Como resultado, calcular cualquier múltiplo de 10 100 conduce a una respuesta igualmente correcta, pero en algunos idiomas, más corta. La respuesta de Dennis allí usa 100 100 , la mía usa 250 255 .

hvd
fuente
44
Otro ejemplo de esto es CJam, donde puede obtener la marca de tiempo actual essi solo necesita un gran número pero no le importa su valor (o que siempre es el mismo).
Martin Ender
10

Compresión Base

El código de descompresión de base puede ser bastante complejo, pero si tiene un número realmente enorme, a veces puede ayudar comprimirlo en una base superior a 10.

También ayuda que en algunos idiomas, el código de compresión base es muy simple. Por ejemplo, PHP tiene base64_decode(_), Python tiene int(_,36), JavaScript tiene parseInt(_,36), y muchos lenguajes de golf tienen bases integradas de descompresión. Por ejemplo, en CJam:

"+ÜTbô±"256b

Esto contiene un no imprimible. Pruébalo en línea!

Esto produce:

12345678987654321
Fruta Esolanging
fuente
9

Usa fracciones exponenciales para números repetitivos grandes

Supongamos que desea generar el número formado por 100 1's. Puede usar int("1"*100), +"1".repeat(100)etc., pero también puede aprovechar el hecho de que está muy cerca de

1e100/9

Esto funciona mejor para números muy repetitivos, como los de un solo dígito. Un par de dígitos repetidos también funciona bastante bien:

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

Ocasionalmente encontrará algún otro patrón extraño que también puede representarse de manera bastante escueta en este método. Si por casualidad necesita int("123456790"*11), por ejemplo:

1e100/81

Sin embargo, tenga cuidado: los números como int("1234567890"*10)no tienen una representación tan fácil.

ETHproducciones
fuente
9

Use Bitwise Left Shift para la exponenciación de 2

Aunque hay muchos lenguajes que admiten operador para exponenciación, algunos no. Y aquellos que no lo hacen, generalmente requieren funciones de llamada (o métodos de Clase / Objeto), que pueden costar unos pocos bytes.

Pero puede guardar algunos bytes cuando necesite elevar 2 a la potencia n utilizando el operador Bitwise Left Shift <<como 1<<n. Tenga en cuenta que esto solo le ahorrará bytes si n es mayor o igual que 17. Sin embargo, esto siempre le ahorrará bytes si n es dinámico. Pocos ejemplos:

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
fuente
44
Tenga en cuenta que puede usar otros valores en lugar de 1. 8<<9 // 4096para que podamos obtener hasta 99<<616 bytes, ¡lo que equivale a 6,917,529,027,641,081,856ahorrar 13 bytes!
Draco18s
@ Draco18s Sí, y está cubierto aquí .
Arjun
Ese más cubre los operadores booleanos bit a bit. Sí, también tiene el desplazamiento de bits, pero se trata de usar dos números grandes para XOR y obtener un tercer número específico.
Draco18s
7

Teorema del resto chino

Si con frecuencia aparecen números enteros arbitrarios, o la representación de números enteros grandes en el lenguaje de programación de destino cuesta demasiados bytes, puede considerar usar el Teorema del resto chino.

Elija algunos enteros relativamente primos por pares m i > = 2, y puede expresar un gran número de 0 a mcm (m 1 , m 2 , ..., m i ) -1

Por ejemplo, elijo 2, 3, 5, 11, 79, 83, 89, 97, luego puedo expresar un número menor que 18680171730 únicamente. 10000000000 (1e10) se puede expresar como 0,1,0,1,38,59,50,49 (1e10 mod 2, 3 ..., 97) que no necesita expresarse como una clase / estructura especial de Big Integer que podría guardar Algunos bytes en algún lenguaje de programación.

La suma y la resta se pueden hacer directamente usando esta representación. Ejemplo:

(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
fuente
1
¿Le importaría detallar eso?
Skidsdev
@Mayube He agregado alguna explicación, pero dudo que sea inútil en la mayoría de los casos.
Aria Axe
1
Es el "teorema del resto".
Ørjan Johansen
6

Use relleno de cadena (cuando sea posible)

Si un número grande incluye un dígito repetido al principio o al final, puede guardar bytes utilizando uno de los métodos de relleno de su idioma para construir una cadena del número que está buscando, que luego puede convertir a un entero.


Ejemplo

Para generar el número 1111111111111111111111112(25 bytes) en JavaScript (ES8):

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

Usar exponentes

Si su idioma tiene un operador de exponente, puede usarlo para generar, si no el número que desea, al menos un número que pueda realizar un cálculo simple o 2 para llegar a su número. Incluso sin un operador, es posible que pueda guardar bytes con una función o método incorporado.

Ejemplo

El número entero máximo seguro en JavaScript es 9007199254740991, que tiene 16 dígitos de largo. En ES7, esto se puede calcular con los siguientes 7 bytes:

2**53-1

El equivalente en ES6 y versiones anteriores, mientras que la misma longitud que el entero en este caso, demuestra que el uso de un método más detallado no necesariamente le costará ningún byte.

Math.pow(2,53)-1

Sin embargo, lo anterior puede resultar más corto si, por ejemplo, ya tiene un Mathalias para un solo carácter en otra parte de su código.

Lanudo
fuente
2

Usa fracciones en el lugar del flotador

Ejemplo: 1./3en lugar de0.333333333

RosLuP
fuente