Imaginando como jogos como o Titan tit e o Cookie Clicker lidam com números tão grandes.
Estou tentando implementar um jogo ocioso, no entanto, o maior formato numérico suportado pelo c # é decimal.
Eu estou olhando para suportar até 10 ^ 500; que precisa ser ponto flutuante
Como eu poderia lidar com isso?
PS: ele precisa ser multiplataforma, ou seja, pc, mac, ios, android e compatível com Unity
unity
mathematics
MathHelp
fonte
fonte
double
. Se fosse eu, eu teria usado o BigInteger .Respostas:
Se você deseja apenas armazenar números enormes sem precisão total, por exemplo, se você mostrar 12.567.000.000.000 como 12.567T (trilhões), basta usar valores padrão de flutuação / decimal e mostrar os primeiros x números significativos, com um sufixo adequado como isso. Quando você está em mais de um milhão, você realmente precisa se preocupar com cada incremento inteiro individual?
fonte
Você pode usar algo como o BigInteger , que só está disponível no .net 4.0 se não me engano (não é suportado por todas as plataformas de criação de unidade).
Existem algumas bibliotecas que tentam trazer essa funcionalidade sem a necessidade de .net4.0. Por exemplo aqui .
Como alternativa, você pode usar números menores para representar um número maior, acompanhando o multiplicador. Por exemplo:
Agora, mesmo que você tenha um valor 9, se você o associar ao seu multiplicador, poderá efetivamente representá-lo como 9 trilhões (ou colocando "trilhão" ou escrevendo algo que acrescentará os zeros no final do seu valor) )
fonte
BigInteger
usar uma representação String ou Byte [] do número - portanto, é possível criar sua própria classe que apenas adiciona e subtrai dois "números como Strings ou Bytes" - ( geralmente esse tipo de jogo não não é necessário, mas você também pode oferecer suporte à multiplicação ou divisão ou outras funções mais avançadas ) - mas eles devem ter em mente que sempre há um limite físico em que a memória pode ficar sem memória.Você provavelmente precisaria escrever sua própria classe para usar no Unity, mas não seria particularmente difícil.
Internamente, poderia ser uma lista de números inteiros (como a
List<int>
), com cada elemento na lista correspondendo a um grupo de 9 dígitos. Cada número inteiro tem um intervalo de 0 a 999 999 999. Um número inteiro pode suportar um pouco mais de 2 bilhões e o dobro se não estiver assinado, mas você deseja que cada "dígito" exceda1 000 000 000
, porque você também deseja para converter facilmente seu grande número em uma string para exibição. É mais fácil concatenar o que já é um dígito decimal (return group[i].ToString() + group[i-1].ToString() and so on
) do que descobrir como exibir a soma dos grupos que estão fora do intervalo de qualquer tipo de dados regular.Portanto, o primeiro int na sua lista representaria 1s. O próximo seria o número de bilhões. O próximo, o número de quatrilhões e assim por diante.
A adição e subtração funcionariam como a adição e subtração de caneta e papel, onde você deve observar o estouro e transportá-lo para o próximo "dígito", mas, em vez de dígitos com um intervalo de 0 a 9, seus dígitos variam de 0 a 999 999 999.
fonte
Para lidar com grandes números, eu consideraria um bom exemplo como Tower of Hero . Canto superior esquerdo:
(fonte: mzstatic.com )
Sem entrar no jogo, a maneira como ele lida com os números é relativamente simples: você vê dois grupos de números. À medida que você sobe na torre e produz mais "ouro", os dois baldes simplesmente representam números maiores.
Quando o jogo passa T, ele se move para a, b, c ... z, aa, ab, ...
Fazendo dessa maneira, ele ainda permite saber quanto ouro você "ganhou" ... sem atrapalhar o jogo em detalhes.
Você realmente se importa com milhões quando seu número ultrapassa os trilhões?
Mantém o número em Int, Big Int, Float, Double, Decimal, ...? Matriz personalizada? Quando você está lidando com números de maneira "confusa", não acho que isso importe ...
Tudo o que importa é a parte mais significativa - neste caso, os 6 primeiros ... Depois disso, TALVEZ os próximos 3 ou 6 - já que ganhar algumas centenas de K pode rolar para milhões - mas há um ponto em que ganhar algumas centenas de K não afetarão você quando você acertar T ... muito menos aa e além.
Sua milhagem varia (dependendo do que você deseja / precisa) ... Só pensei em colocar meu 2c no que acho um exemplo bom / simples.
Editar:
Pensamentos adicionais sobre como eu implementaria o sistema de numeração: eu teria um número com três partes significativas: XXXX.YYY (...) xZZZ.
Então 120.365x1 seria 120k365 ... 120.365x2 seria 120M365K ... etc. Bata os 4 à esquerda (1200.365x2) e gire os números 1.200365 (...) x3. Bam. Você tem 1B200M.
XY caberia facilmente em um decimal ou flutuante ... com Z sentado próximo a ele como int / unsigned int.
Com um flutuador, você poderá manter um número considerável - mas cada vez mais sem importância - de dígitos após o ponto.
Z representaria facilmente um bloco de números facilmente compreensível:
fonte
E a maneira mais fácil de lidar com números grandes é simplesmente ter mais de um valor INTEGER e carregar qualquer excesso. Se você possui um valor INT de 16 bits (0 a 65535) e deseja ter mais do que isso, use dois valores INT de 16 bits em uma linha. Pense nisso como ter um valor BYTE (0 a 255), mas usando apenas até 99 dígitos de valor. Quando atingir 100, passe-o para o próximo valor mais alto de BYTE, com o número de dígitos que achar útil. Com os computadores GHZ de hoje, até uma codificação desleixada é boa.
Obviamente, existe uma alternativa um pouco mais rápida.
Se você estiver adicionando 18 repetidamente a um número, é mais rápido subtrair 2 e adicionar 20. 18, 36, 54, 72, 90, 108, ... 18 = 20 + (- 2).
Também funciona em binário. (Mesmos valores decimais em binário) 10010, 100100, 110110, 1001000
DEC (18) = BIN (10010)
Exceto para uma análise binária mais fácil, você precisa pensar em 18 = 16 + 2
DEC (16 + 2) = BIN (10000 + 00010). Se o valor for 15, pense nele como adicionando 16 no binário e subtraindo 1 (10000-00001).
Dessa forma, você pode manter os blocos de números em limites gerenciáveis por valor.
Se você estiver usando o método de codificação superficial de limitar um valor INT básico de 16 bits (0 a 65535) a um limite decimal de 4 dígitos (0 a 9999), tudo o que você precisa fazer é quando o valor exceder o limite 9999, subtraia 9999 e leve-o para o próximo pedaço de valor (já que você está fazendo basicamente "adiciona e sub" com números versus um cálculo binário real).
Idealmente, você usaria a MATEMÁTICA SIMBÓLICA que aprendeu na escola. Como é que isso funciona. Se você possui o símbolo decimal de 1 e o adiciona a 1, obtém o símbolo decimal de 2. O motivo pelo qual eu chamo isso de símbolo é que você poderia usar qualquer série de símbolos com uma tabela de pesquisa "SE símbolo X (1) é adicionado ao símbolo X (4) ENTÃO, símbolo de saída X (5) ". O símbolo X (1) pode ser uma imagem de um gato e o símbolo X (4) pode ser o sinal PERCENT, mas isso não importa. Você tem seus símbolos, um livro de regras básico do que acontece e depois esses símbolos são combinados (como as tabelas de multiplicação que você memorizou quando criança) e qual símbolo deve resultar como parte dessa operação. Com o uso da Symbolic Math, você pode adicionar um número infinito de dígitos sem nunca chamar os limites numéricos do seu processador.
Uma maneira de fazer isso na codificação fácil é ter cada dígito representado com o qual você deseja trabalhar como uma única unidade em uma grande matriz dimensionada. Se você deseja representar 4096 dígitos decimais (não excedendo 2 dígitos por caixa de unidade), aloque 2 conjuntos de locais da matriz 4096 BYTE. Armazenar o valor de 1098874 utilizaria a matriz como (1) (0) (9) (8) (8) (7) (4). Se você adicionou o valor de 7756 a ele, você o converteria em (7) (7) (5) (6) e depois o adicionaria. O resultado seria (1) (0) (9) (15) (15) (12) (10) que você subtrairia da direita para a esquerda até que todas as caixas de dígitos fossem normalizadas para serem o valor de (0 a 9) O valor mais à direita (10) teria 10 subtraído e o valor resultante seria zero (0) e isso levaria o valor (1) para a próxima caixa à esquerda de (12) para torná-lo (13), que então teria 10 subtraído para transformá-lo em (3).
fonte
`text`
→text
) o tornará espaçado em mono, apropriado para blocos de código, nomes de funções, dados, etc. Quebrar texto em sublinhados ou asteriscos o tornará em itálico (_text_
ou*text*
→ texto ) e em sublinhado duplo ou duplo os asteriscos ficarão em negrito (__text__
ou**text**
→ texto ).O que você faz é ter várias variáveis combinadas e, em seguida, você controla a adição e o excesso entre elas. Você pode ter qualquer número de dígitos dessa maneira. Combine 10.000 números inteiros de 32 bits e você terá um número com 32.000 bits, se é isso que você precisa. Não há limite em nenhuma linguagem de programação. O único limite é o que você é capaz de descobrir.
fonte
double
ouBigInteger
.