Je me demande simplement comment des jeux tels que Tap titans et Cookie Clicker gèrent de si grands nombres.
J'essaie d'implémenter un jeu inactif, mais le plus grand format numérique pris en charge par C # est décimal.
Je cherche à prendre en charge jusqu'à 10 ^ 500; qui doit être en virgule flottante
Comment pourrais-je gérer cela?
PS, il doit être multiplateforme, c'est-à-dire pc, mac, ios, android et compatible avec Unity
unity
mathematics
MathHelp
la source
la source
double
. Si ça avait été moi, j'aurais utilisé BigInteger .Réponses:
Si vous voulez simplement stocker des nombres massifs sans précision complète, par exemple si vous allez afficher 12 567 000 000 000 comme 12,567 T (trillions), vous pouvez simplement utiliser des valeurs flottantes / décimales standard et afficher les premiers x chiffres significatifs, avec un suffixe approprié comme ça. Lorsque vous êtes dans les octillions, avez-vous vraiment besoin de vous soucier de chaque incrément entier individuel?
la source
Vous pouvez utiliser quelque chose comme BigInteger , qui n'est disponible dans .net 4.0 que si je ne me trompe pas (non pris en charge par toutes les plates-formes de construction d'unité).
Certaines bibliothèques tentent cependant d'apporter cette fonctionnalité sans l'exigence de .net4.0. Par exemple ici .
Alternativement, vous pouvez utiliser des nombres plus petits pour représenter un plus grand, en gardant une trace du multiplicateur. Par exemple:
Maintenant, même si vous avez une valeur de 9, si vous l'associez à votre multiplicateur, vous pouvez effectivement représenter ce 9 comme 9 trillions (soit en mettant "trillion" ou en écrivant quelque chose qui ajoutera les zéros à la fin de votre valeur ).
la source
BigInteger
utilisation d'une représentation String ou Byte [] du nombre - en fait, on pourrait créer leur propre classe qui ajoute et soustrait simplement deux "nombres sous forme de chaînes ou d'octets" - ( généralement ce type de jeu ne fait pas pas besoin, mais vous pouvez également prendre en charge la multiplication ou la division ou d'autres fonctions plus avancées ) - mais ils doivent garder à l'esprit qu'il existe toujours une limite physique où ils peuvent manquer de mémoire.Vous auriez probablement besoin d'écrire votre propre classe pour l'utiliser dans Unity, mais ce ne serait pas particulièrement difficile.
En interne, il peut s'agir d'une liste d'entiers (comme a
List<int>
), chaque élément de la liste correspondant à un groupe de 9 chiffres. Chaque entier aurait une plage de 0 à 999 999 999. Un entier peut prendre en charge un peu plus de 2 milliards, et le doubler s'il n'est pas signé, mais vous voudrez que chaque "chiffre" déborde1 000 000 000
, car vous voudrez également pour pouvoir facilement convertir votre grand nombre en une chaîne à afficher. Il est plus facile de concaténer des chiffres déjà décimaux (return group[i].ToString() + group[i-1].ToString() and so on
) que de déterminer comment afficher la somme des groupes qui se trouvent en dehors de la plage de tout type de données standard.Ainsi, le premier entier de votre liste représenterait 1s. Le prochain serait le nombre de milliards. Le suivant, le nombre de quadrillions, et ainsi de suite.
L'addition et la soustraction fonctionneraient exactement comme l'addition et la soustraction au stylo et papier, où vous devez surveiller le débordement et le reporter au "chiffre" suivant, mais au lieu de chiffres avec une plage de 0 à 9, vos chiffres vont de 0 à 999 999 999.
la source
Pour gérer de grands nombres, je regarderais ce que je pense être un bon exemple comme Tower of Hero . Coin supérieur gauche:
(source: mzstatic.com )
Sans entrer dans le gameplay, la façon dont il gère les nombres est relativement simple: vous voyez deux groupes de nombres. Lorsque vous montez plus haut dans la tour et que vous faites plus "d'or", les deux seaux représentent simplement de plus grands nombres.
Une fois que le jeu passe T, il se déplace en a, b, c ... z, aa, ab, ...
En procédant de cette façon, cela vous permet toujours de savoir combien d'or vous avez "gagné" ... tout en n'embourbant pas le jeu dans les détails.
Vous souciez-vous vraiment des millions quand votre nombre est passé des milliards?
Conserve-t-il le nombre en Int, Big Int, Float, Double, Decimal, ...? Tableau personnalisé? Lorsque vous gérez des nombres de manière si "floue", je ne pense pas que cela soit important ...
Tout ce qui compte probablement, ce sont les parties les plus importantes - dans ce cas, les 6 premiers ... Après cela, PEUT-ÊTRE les 3 ou 6 suivants - puisque gagner quelques centaines de K peut se transformer en millions - mais il y a un point où gagner quelques centaines de K ne vous affecteront pas lorsque vous frapperez T ... encore moins aa et au-delà.
Votre kilométrage variera (en fonction de ce que vous voulez / besoin) ... Je pensais simplement que je mettrais mon 2c sur ce que je pense être un bon / simple exemple.
Modifier:
Réflexions supplémentaires sur la façon dont j'implémenterais le système de numérotation: j'aurais un nombre avec 3 parties significatives: XXXX.YYY (...) xZZZ.
Donc 120.365x1 serait 120k365 ... 120.365x2 serait 120M365K ... etc. Appuyez sur le 4 en tête (1200.365x2), puis faites simplement pivoter les nombres 1.200365 (...) x3. Bam. Vous avez 1B200M.
XY s'intégrerait facilement dans une décimale ou un flottant ... avec Z assis à côté comme un int / non signé.
Avec un flotteur, vous seriez en mesure de conserver un nombre important - mais de plus en plus insignifiant - de chiffres après le point.
Z représenterait facilement un bloc de nombres facilement compréhensible:
la source
Et un moyen facile de gérer de grands nombres est simplement d'avoir plus d'une valeur INTEGER puis de TRANSPORTER tout débordement. Si vous avez une valeur INT 16 bits (0 à 65535) et que vous souhaitez en avoir plus, utilisez deux valeurs INT 16 bits consécutives. Pensez-y comme ayant une valeur BYTE (0 à 255) mais en l'utilisant uniquement jusqu'à 99 chiffres. Une fois qu'il atteint 100, passez-le à la prochaine valeur d'octet supérieure pour autant de chiffres que vous trouvez utiles. Avec les ordinateurs GHZ d'aujourd'hui, même un codage bâclé comme ça est bien.
Bien sûr, il existe une alternative un peu plus rapide.
Si vous ajoutez 18 à plusieurs reprises à un nombre, il est plus rapide de simplement soustraire 2 et d'ajouter 20. 18, 36, 54, 72, 90, 108, ... 18 = 20 + (- 2).
Cela fonctionne aussi en binaire. (Mêmes valeurs décimales en binaire) 10010, 100100, 110110, 1001000
DEC (18) = BIN (10010)
À l'exception d'une analyse binaire plus facile, vous devez penser à 18 = 16 + 2
DEC (16 + 2) = BIN (10000 + 00010). Si la valeur était 15, alors considérez-la comme l'ajout de 16 en binaire et la soustraction de 1 (10000-00001).
De cette façon, vous pouvez limiter le nombre de morceaux à des limites gérables par valeur.
Si vous utilisez la méthode de codage bâclée pour limiter une valeur INT 16 bits de base (0 à 65535) à une limite décimale à 4 chiffres (0 à 9999), alors tout ce que vous avez à faire est lorsque la valeur dépasse la limite 9999, soustrayez-en 9999 et portez-le au bloc de valeur suivant (puisque vous faites essentiellement des «ajouts et sous-marins» avec des nombres par rapport à un vrai calcul binaire).
Idéalement, vous utiliseriez simplement SYMBOLIC MATH que vous avez appris à l'école primaire. Comment cela marche-t-il. Si vous avez le symbole décimal de 1 et que vous l'ajoutez à 1, vous obtenez le symbole décimal de 2. La raison pour laquelle j'appelle cela un symbole est que vous pouvez utiliser n'importe quelle série de symboles avec une table de correspondance de "SI symbole X (1) est ajouté au symbole X (4) ALORS symbole de sortie X (5) ". Le symbole X (1) pourrait être une image d'un chat et le symbole X (4) pourrait être le signe PERCENT, mais cela n'a pas d'importance. Vous avez vos symboles, un livre de règles de base de ce qui se passe, puis ces symboles sont combinés (un peu comme les tables de multiplication que vous avez mémorisées en tant qu'enfant) et quel symbole doit résulter dans le cadre de cette opération. En utilisant Symbolic Math, vous pouvez ajouter un nombre infini de chiffres sans jamais vraiment appeler les limites numériques de votre processeur.
Une façon de le faire dans un codage facile est d'avoir chaque chiffre représenté avec lequel vous souhaitez travailler comme une seule unité dans un tableau de grande dimension. Si vous souhaitez représenter 4096 chiffres décimaux (ne dépassant pas 2 chiffres par boîte d'unité), vous allouez 2 ensembles d'emplacements de tableau 4096 BYTE. Le stockage de la valeur de 1098874 utiliserait la matrice comme (1) (0) (9) (8) (8) (7) (4). Si vous y ajoutez la valeur de 7756, vous la convertissez en (7) (7) (5) (6) puis ajoutez. Le résultat serait (1) (0) (9) (15) (15) (12) (10) que vous devez ensuite soustraire de droite à gauche jusqu'à ce que toutes les cases de chiffres soient normalisées pour être la valeur de (0 à 9). La valeur la plus à droite (10) aurait 10 soustrait et la valeur résultante serait zéro (0) et cela porterait la valeur (1) à la case de gauche suivante de (12) pour en faire (13) qui aurait alors 10 soustrait pour en faire (3).
la source
`text`
→text
) , il sera mono-espacés, appropriés pour des morceaux de code, les noms de fonction, les données, etc. Texte d'emballage en underscores ou astérisques il sera en italique (_text_
ou*text*
→ texte ), et double-underscores ou double les astérisques le mettront en gras (__text__
ou**text**
→ texte ).Ce que vous faites est de combiner plusieurs variables, puis vous contrôlez vous-même l'ajout et le débordement entre elles. Vous pouvez avoir n'importe quel nombre de chiffres de cette façon. Combinez 10 000 entiers 32 bits, et vous avez un nombre avec 32 000 bits, si c'est ce dont vous avez besoin. Il n'y a aucune limite dans aucun langage de programmation. La seule limite est ce que vous pouvez comprendre.
la source
double
ouBigInteger
.