Me pregunto cómo los juegos como Tap titans y Cookie Clicker manejan números tan grandes.
Estoy tratando de implementar un juego inactivo, sin embargo, el formato de número más grande admitido por C # es decimal.
Estoy buscando soportar hasta 10 ^ 500; eso tiene que ser punto flotante
¿Cómo podría manejar esto?
PD: debe ser multiplataforma, es decir, PC, Mac, iOS, Android y compatible con Unity
unity
mathematics
MathHelp
fuente
fuente
double
. Sin embargo, si hubiera sido yo, habría usado BigInteger .Respuestas:
Si solo desea almacenar números masivos sin precisión completa, por ejemplo, si va a mostrar 12,567,000,000,000 como 12.567T (billones), puede usar valores estándar flotantes / decimales y mostrar las primeras x cifras significativas, con un sufijo adecuado Me gusta esto. Cuando estás en los octillones, ¿realmente necesitas preocuparte por cada incremento entero individual?
fuente
Podría usar algo como BigInteger , que solo está disponible en .net 4.0 si no me equivoco (no es compatible con todas las plataformas de construcción de la unidad).
Sin embargo, hay algunas bibliotecas que intentan llevar esta funcionalidad sin el requisito de .net4.0. Por ejemplo aquí .
Alternativamente, puede usar números más pequeños para representar uno más grande, haciendo un seguimiento del multiplicador. Por ejemplo:
Ahora, aunque tenga un valor de 9, si lo combina con su multiplicador, puede representar efectivamente ese 9 como 9 billones (ya sea poniendo "billones" o escribiendo algo que agregará los ceros al final de su valor )
fuente
BigInteger
uso de una representación String o Byte [] del número, por lo que en realidad se podría crear su propia clase que simplemente suma y resta dos "números como Strings o Bytes" - ( generalmente este tipo de juego no no lo necesita, pero también podría admitir la multiplicación o división u otras funciones más avanzadas ), pero tendrían que tener en cuenta que siempre hay un límite físico en el que pueden quedarse sin memoria.Es probable que necesite escribir su propia clase para usar en Unity, pero no sería particularmente difícil.
Internamente, podría ser una lista de enteros (como a
List<int>
), con cada elemento en la lista correspondiente a un grupo de 9 dígitos. Cada número entero tendría un rango de 0 a 999 999 999. Un número entero puede admitir un poco más de 2 mil millones, y duplicarlo si no está firmado, pero querrá tener cada desbordamiento de "dígito"1 000 000 000
, porque también querrá para poder convertir fácilmente su número grande en una cadena para mostrar. Es más fácil concatenar lo que ya son dígitos decimales (return group[i].ToString() + group[i-1].ToString() and so on
) que descubrir cómo mostrar la suma de grupos que están fuera del rango de cualquier tipo de datos regular.Entonces, el primer int en su lista representaría 1s. El siguiente sería el número de miles de millones. El siguiente, el número de cuatrillones, y así sucesivamente.
La suma y la resta funcionarían igual que la suma y resta de lápiz y papel, donde debe observar el desbordamiento y llevarlo al siguiente "dígito", pero en lugar de dígitos con un rango de 0-9, sus dígitos van desde 0 a 999999999.
fuente
Para manejar números grandes, miraría lo que creo que es un buen ejemplo como Tower of Hero . Esquina superior izquierda:
(fuente: mzstatic.com )
Sin entrar en el juego, la forma en que maneja los números es relativamente simple: ves dos cubos de números. A medida que asciendes en la torre y haces más "oro", los dos cubos simplemente representan números más grandes.
Una vez que el juego pasa T, se mueve a a, b, c ... z, aa, ab, ...
Al hacerlo de esta manera, todavía te permite saber cuánto oro has "ganado" ... sin atascar el juego en detalles.
¿Realmente te importan Millones cuando tu número supera los Trillones?
¿Mantiene el número en Int, Big Int, Float, Double, Decimal, ...? Matriz personalizada? Cuando manejas números de una manera tan "difusa", no creo que importe ...
Todo lo que probablemente importa son las partes más importantes, en este caso, los primeros 6 ... Después de eso, tal vez los próximos 3 o 6, ya que ganar unos cientos de K puede pasar a Millones, pero hay un punto en el que ganar unos pocos cientos de K no te afectarán cuando golpees T ... mucho menos aa y más allá.
Su millaje variará (dependiendo de lo que quiera / necesite) ... Solo pensé que pondría mi 2c en lo que creo que es un buen / simple ejemplo.
Editar:
Más ideas sobre cómo implementar el sistema de numeración: tendría un número con 3 partes significativas: XXXX.YYY (...) xZZZ.
Por lo tanto, 120.365x1 sería 120k365 ... 120.365x2 sería 120M365K ... etc. Presione los 4 primeros (1200.365x2), luego gire los números 1.200365 (...) x3. Bam Tienes 1B200M.
XY encajaría fácilmente en un decimal o flotante ... con Z sentado a su lado como int / unsigned int.
Con un flotador, podrá mantener una cantidad considerable, pero cada vez menos importante, de dígitos después del punto.
Z representaría fácilmente un bloque de números fácilmente comprensible:
fuente
Y una manera fácil de manejar grandes números es simplemente tener más de un valor INTEGER y luego TRANSPORTAR cualquier desbordamiento. Si tiene un valor INT de 16 bits (0 a 65535) y desea tener más que eso, use dos valores INT de 16 bits en una fila. Piense en ello como tener un valor BYTE (0 a 255) pero solo usarlo hasta 99 dígitos de valor. Una vez que llegue a 100, luego gírelo al siguiente valor BYTE más alto para todos los dígitos que considere útiles. Con las computadoras GHZ actuales, incluso una codificación descuidada como esa está bien.
Por supuesto, hay una alternativa que es un poco más rápida.
Si sumas 18 repetidamente a un número, es más rápido restar simplemente 2 y sumar 20. 18, 36, 54, 72, 90, 108, ... 18 = 20 + (- 2).
Funciona en binario también. (Los mismos valores decimales en binario) 10010, 100100, 110110, 1001000
DEC (18) = BIN (10010)
Excepto para un análisis binario más fácil, debe pensar en 18 = 16 + 2
DEC (16 + 2) = BIN (10000 + 00010). Si el valor era 15, piense en ello como sumando 16 en binario y restando 1 (10000-00001).
De esta manera, puede mantener los fragmentos de números en límites manejables por valor.
Si está utilizando el método de codificación descuidada de limitar un valor INT básico de 16 bits (0 a 65535) a un límite decimal de 4 dígitos (0 a 9999), entonces todo lo que tiene que hacer es cuando el valor excede el límite de 9999, reste 9999 y llévelo al siguiente fragmento de valor (ya que básicamente está haciendo "sumas y subs" con números versus un cálculo binario real).
Idealmente, solo usarías MATEMÁTICA SIMBÓLICA que aprendiste en la escuela primaria. Como funciona esto. Si tiene el símbolo decimal de 1 y lo agrega a 1, entonces obtiene el símbolo decimal de 2. La razón por la que llamo a esto un símbolo es que podría usar cualquier serie de símbolos con una tabla de búsqueda de "símbolo IF X (1) se agrega al símbolo X (4) ENTONCES el símbolo de salida X (5) ". El símbolo X (1) podría ser una imagen de un gato y el símbolo X (4) podría ser el signo de PORCENTAJE, pero no importa. Tienes tus símbolos, un libro de reglas básico de lo que sucede, luego esos símbolos se combinan (algo así como las tablas de multiplicar que memorizaste cuando eras niño) y qué símbolo debe resultar como parte de esa operación. Con el uso de Symbolic Math, puede agregar un número infinito de dígitos sin tener que invocar los límites numéricos de su procesador.
Una forma de hacer esto en una codificación fácil es tener cada dígito representado con el que desea trabajar como una sola unidad en una matriz de dimensiones grandes. Si desea representar 4096 dígitos decimales (que no excedan 2 dígitos por caja de unidad), entonces asigne 2 conjuntos de ubicaciones de matriz 4096 BYTE. El almacenamiento del valor de 1098874 utilizaría la matriz como (1) (0) (9) (8) (8) (7) (4). Si le agregaste el valor de 7756, lo convertirías en (7) (7) (5) (6) y luego lo sumarías. El resultado sería (1) (0) (9) (15) (15) (12) (10) que luego restaría de derecha a izquierda con desplazamiento hasta que todos los cuadros de dígitos se normalizaron para ser el valor de (0 a 9) El valor más a la derecha (10) tendría 10 restados y el valor resultante sería cero (0) y eso llevaría el valor (1) al cuadro siguiente-izquierdo de (12) para convertirlo en (13) que luego tendría 10 restado para convertirlo en (3).
fuente
`text`
→text
) lo hará en un espacio sencillo, apropiado para fragmentos de código, nombres de funciones, datos, etc. El texto en minúsculas o asteriscos lo pondrá en cursiva (_text_
o*text*
→ texto ), y doble guión bajo o doble- los asteriscos lo pondrán en negrita (__text__
o**text**
→ texto ).Lo que haces es combinar varias variables, y luego controlas la adición y el desbordamiento entre ellas. Puede tener cualquier número de dígitos de esa manera. Combine 10,000 enteros de 32 bits y obtendrá un número con 32,000 bits, si eso es lo que necesita. No hay límite en ningún lenguaje de programación. El único límite es lo que eres capaz de resolver.
fuente
double
o noBigInteger
.