アイドルゲームは、このような多数をどのように処理しますか?


31

Tap titansやCookie Clickerなどのゲームがこのような大きな数字をどのように処理するのか不思議に思っています。

アイドルゲームを実装しようとしていますが、C#でサポートされている最大の数値形式は10進数です。

最大10 ^ 500までサポートしたいと考えています。浮動小数点である必要があります

どうすればこれを処理できますか?

PSそれはクロスプラットフォームである必要がありますすなわちPC、Mac、IOS、AndroidとUnityとの互換性


2
私の記憶が正しければ、あなたはちょうどそれをチェックすることができますので、あなたは、クッキークリッカーのコードへのアクセス権を持っている...
Vaillancourt

いいえ、すでにCookie Clickerを頭からブロックしていました!
アルトゥーロトーレスサンチェス

2
UnityのゲームであるTimeClickersの逆コンパイルされたソースを見てきました。彼らはただ使用しますdouble。私だったら、BigIntegerを使用していたでしょう。
BlueRaja-ダニーPflughoeft

1
@VioletGiraffe:同意します。(私たちの)疑問を具体的にしたいです(OPが質問をより明確にするのを助けるために):質問に関する「アイドルゲーム」とはゲームの数が多い場合の特殊なケース)?「そのような大きな数字」(自分で強調)とはどのような数字を指しますか?数字をどれくらい大きくしたいですか?
またはマッパー

そのような大きな数をいつでも文字列に格納し、文字列の合計を行う関数を簡単に実装できます。
DEV-masih

回答:


40

12.567T(兆)として12,567,000,000,000を表示する場合など、完全な精度なしで大量の数値を保存する場合は、標準の浮動小数点/ 10進数値を使用し、最初のx有効数字を適切なサフィックスで表示することができますこのような。あなたが10億にいるとき、あなたは本当に個々の整数増分を気にする必要がありますか?


4
これはおそらく最も賢明な答えであり、Cookie ClickerはJavaScriptで標準のフロートを使用していることをかなり確信しています-私がそれを「ハッキング」した場合(読み取り:コンソールを台無しにして)、数が1e308に達したときにジャンプしました「インフィニティ」へと私はXD欲しかったものを購入するために進むことができ
Nietダークアブソル

1
すばらしいです!テキストが「Infinity」にジャンプするという事実は、開発者がこの偶発性についても防御的にコーディングしているように感じます。また、シンプルさが重要です。
ロステイラーターナー

19
@RossTurner-「Infinity」というテキストを表示するためのコーディングはおそらくありませんでした。無限はフロートが持つことができる単なる値であり、JavaScriptは他の多くの言語と同様に表示方法を知っています。
ジブスマート

標準の浮動小数点数(倍精度、8バイト)では、元の質問が要求するように10 ^ 500までの数値を表すことはできません。最大で10 ^ 300になります。それで十分でない場合は、言語によっては自明ではない4倍精度の浮動小数点数を使用する必要があります。
ペティス

1
すべてのプログラマーが浮動小数点数について知っておくべきこと:floating
スティーブ

20

BigIntegerのようなものを使用できます。BigIntegerは、.net 4.0でのみ使用可能です(すべてのユニティビルドプラットフォームでサポートされているわけではありません)。

ただし、.net4.0を必要とせずにこの機能を提供しようとするライブラリがいくつかあります。例えばここに

または、乗数を追跡することで、小さい数字を使用して大きい数字を表すことができます。例えば:

double value = 9;
enum Multiplier {
   Hundred,
   Thousand,
   Million,
   Billion,
   Trillion
}

現在、値が9であっても、乗数と組み合わせると、9を9兆として効果的に表すことができます(「兆」を入力するか、値の末尾にゼロを追加する何かを書くことで) )。


BigInteger数字のStringまたはByte []表現を使用するなどのクラス-つまり、実際には2つの「文字列またはバイトとしての数字」を加算および減算する独自のクラスを作成できます-(通常、このタイプのゲームは必要ありませんが、乗算や除算などのより高度な機能もサポートできます)-しかし、メモリ不足になる可能性のある物理的な制限は常に存在することに留意する必要があります。
ダブルダブル

1
各バイトは、数値のサイズに256を掛けます。数値を表現しようとしてメモリが不足すると、数値には実際の値がありませんでした。256 ^(20億)= 2 ^ 8 ^(20億)= 2 ^(160億)〜= 10 ^(50億)(wolframalphaはその最後の変換を行おうとして壊れました)。150桁(<500ビット)などを使用して、オブザーバブルユニバースで個々のPlanckボリュームを指定できます。
MichaelS

11

Unityで使用するために独自のクラスを作成する必要があるかもしれませんが、それほど難しくはありません。

内部的には、リストのList<int>各要素が9桁のグループに対応する整数のリスト(など)である可能性があります。各整数の範囲は0〜999 999 999です。整数は20億強をサポートし、符号なしの場合は2倍になりますが、で各「桁」がオーバーフローするよう1 000 000 000にする必要があります。大きい数字を表示用の文字列に簡単に変換できるようにします。return group[i].ToString() + group[i-1].ToString() and so on通常のデータ型の範囲外にあるグループの合計を表示する方法を理解するよりも、既に10進数()であるものを連結する方が簡単です。

したがって、リストの最初のintは1を表します。次は数十億です。次に、quadrillionsの数など。

加算と減算は、ペンと紙の加算と減算のように機能します。オーバーフローを監視して次の「桁」に持ち越す必要がありますが、0〜9の範囲の数字ではなく、 0から999 999 999。


10

大きな数字を扱うために、私はヒーローの塔のような良い例だと思うものを見ます。左上隅:

1

2
(ソース:mzstatic.com

ゲームプレイに入ることなく、数字を処理する方法は比較的簡単です。数字の2つのバケットが表示されます。タワーで高くなり、より多くの「ゴールド」を作成すると、2つのバケットは単純に大きな数字を表します。

120 
120M320K - 120 Million
120B631M - 120 Billion
120T134B - 120 Trillion

ゲームがTを通過すると、a、b、c ... z、aa、ab、...に移動します

56aa608z

このようにすることで、ゲームを詳細に行き詰まらせずに、「獲得」した金の量を知ることができます。

あなたの数が兆を超えているとき、あなたは本当に何百万人を気にしますか?

Int、Big Int、Float、Double、Decimalなどの数値を保持しますか?カスタム配列?このような「ファジー」な方法で数値を処理している場合、それは重要ではないと思います...

おそらく重要なのは最も重要な部分です-この場合、最初の6 ...その後、次の3または6になります-数百Kを稼ぐと何百万人に転がることができます-しかし、稼ぐポイントがありますTを押しても数百Kは影響しません。

あなたの走行距離は(あなたが望む/必要とするものに応じて)異なります...ちょうど私が良い/単純な例であると思うものに私の2cを出すと思った。

編集:

番号システムをどのように実装するかについてのさらなる考え:私は、3つの重要な部分を持つ番号を持っています:XXXX.YYY(...)xZZZ。

X is the most significant digits, 
Y trailing 
Z the multiplier (multiple of 3).

120.365x1は120k365 ... 120.365x2は120M365K ...などです。先頭の4つ(1200.365x2)を押してから、数字を1.200365(...)x3だけ回転させます。バム。1B200Mがあります。

XYはDecimalまたはFloatに簡単に収まります。Zはその隣にint / unsigned intとして座っています。

フロートを使用すると、ドットの後の桁数を大きくすることができますが、ますます重要ではなくなります。

Zは、簡単に理解できる数字のブロックを簡単に表します。

K = 1
M = 2
B = 3
T = 4
a = 5 
...
z = 31 (I may be off on this)
aa = 32
...
az = 58
ba = 59
...
...

1

そして、大きな数を処理する簡単な方法は、複数のINTEGER値を持ち、オーバーフローをキャリーすることです。16ビットのINT値(0〜65535)があり、それ以上にしたい場合は、2つの16ビットINT値を連続して使用します。BYTE値(0〜255)を持つが、最大99桁の値のみを使用するようなものだと考えてください。100に達したら、有用な桁数だけ次に大きいBYTE値にロールオーバーします。今日のGHZコンピューターでは、そのようなずさんなコーディングでも問題ありません。

もちろん、もう少し速い選択肢があります。
数に18を繰り返し追加する場合、単に2を減算して20を加算する方が高速です。18、36、54、72、90、108、... 18 = 20 +(-2)。
バイナリでも動作します。(バイナリの同じ10進値)10010、100100、110110、1001000
DEC(18)= BIN(10010)
簡単なバイナリ解析を除き、18 = 16 + 2
DEC(16 + 2)= BIN(10000 + 00010)。値が15だった場合、バイナリで16を加算し、1(10000-00001)を減算すると考えてください。

このようにして、値ごとにチャンクの数を管理可能な制限に保つことができます。
基本的な16ビットINT値(0〜65535)を4桁の10進数の制限(0〜9999)に制限するずさんなコーディング方法を使用している場合は、値が9999の制限を超えたらそれから9999を引き、それを次の値のチャンクに運びます(基本的に、数値と実際のバイナリ計算で「加算と加算」を行うため)。

理想的には、小学校で学んだシンボル数学を使用するだけです。これはどのように作動しますか。小数点記号が1で、それを1に追加すると、小数点記号が2になります。これを記号と呼ぶ理由は、「IF symbol X(1)」のルックアップテーブルで任意の記号シリーズを使用できるからです。シンボルX(4)に追加された後、シンボルX(5)を出力します。シンボルX(1)は猫の絵であり、シンボルX(4)はPERCENT記号である可能性がありますが、それは重要ではありません。あなたのシンボル、何が起こるかについての基本的なルールブックがあり、それらのシンボルは結合され(子供として記憶した掛け算テーブルのようなもの)、どのシンボルがその演算の一部として結果として生じなければなりません。Symbolic Mathを使用すると、プロセッサの数値制限を実際に呼び出すことなく、無限の桁数を追加できます。

簡単なコーディングでこれを行う1つの方法は、大規模な配列内の単一のユニットとして作業したい各表現された数字を持つことです。4096の10進数(ユニットボックスあたり2桁を超えない)を表現する場合は、2セットの4096 BYTE配列位置を割り当てます。1098874の値を保存すると、配列は(1)(0)(9)(8)(8)(7)(4)として使用されます。7756の値を追加した場合は、(7)(7)(5)(6)に変換してから追加します。結果は(1)(0)(9)(15)(15)(12)(10)になり、すべての数字ボックスが(0から9)。右端(10)の値は10減算され、結果の値はゼロ(0)になり、(1)の値が(12)の次の左のボックスに送られて(13)になり、10になります減算して(3)にします。


7
-1あまりにも多くの叫び
スリップD.トンプソン

5
@Gridlockさん、あなたがまったく新しいユーザーであることに気付いたばかりです。ようこそ。私のダウン票は永続的ではないことを明確にする必要があります。それは建設的な批判として意図されています。あなたが提供した答えには価値があり、私が要求している修正を行ったら、私は喜んでそれを賛成票に変更します。また、SEはフォーラムではないことに注意してください。良い答えは読んで忘れてしまうのではなく、時間の経過とともに担当者への配当を支払います。あちこちで答えを修正すると、コミュニティと担当者の助けになります。私はあなたを追い払わなかったと思います。再び、歓迎します、そして、私はあなたが私のアドバイスを使うことを望みます。
スリップD.トンプソン

1
私が提供するもう1つの提案は、すべて大文字ではなく基本的なMarkdownフォーマットを使用することです。バックティック(`text`text)でテキストを折り返すと、コードのチャンク、関数名、データなどに適したモノスペースになります。アンダースコアまたはアスタリスクでテキストを折り返すと、イタリック(_text_または*text*テキスト)になり、ダブルアンダースコアまたはダブルアスタリスクは太字(__text__または**text**テキスト)にします。
スリップD.トンプソン

0

あなたがすることは、いくつかの変数を組み合わせて、それらの間の追加とオーバーフローを自分で制御することです。そのように任意の数の桁を使用できます。10,000個の32ビット整数を組み合わせると、32,000ビットの数値が必要になります。プログラミング言語に制限はありません。唯一の制限は、把握できるものです。


ダウン票を与えた人については、その理由を説明できますか?これが一般的なソリューションではない場合や、労力を必要としない場合でも、ソリューションであり、doubleまたはをサポートしていない言語/プラットフォームでも同じことが可能ですBigInteger
TomTsagk
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.