Tap titansやCookie Clickerなどのゲームがこのような大きな数字をどのように処理するのか不思議に思っています。
アイドルゲームを実装しようとしていますが、C#でサポートされている最大の数値形式は10進数です。
最大10 ^ 500までサポートしたいと考えています。浮動小数点である必要があります
どうすればこれを処理できますか?
PSそれはクロスプラットフォームである必要がありますすなわちPC、Mac、IOS、AndroidとUnityとの互換性
Tap titansやCookie Clickerなどのゲームがこのような大きな数字をどのように処理するのか不思議に思っています。
アイドルゲームを実装しようとしていますが、C#でサポートされている最大の数値形式は10進数です。
最大10 ^ 500までサポートしたいと考えています。浮動小数点である必要があります
どうすればこれを処理できますか?
PSそれはクロスプラットフォームである必要がありますすなわちPC、Mac、IOS、AndroidとUnityとの互換性
回答:
12.567T(兆)として12,567,000,000,000を表示する場合など、完全な精度なしで大量の数値を保存する場合は、標準の浮動小数点/ 10進数値を使用し、最初のx有効数字を適切なサフィックスで表示することができますこのような。あなたが10億にいるとき、あなたは本当に個々の整数増分を気にする必要がありますか?
BigIntegerのようなものを使用できます。BigIntegerは、.net 4.0でのみ使用可能です(すべてのユニティビルドプラットフォームでサポートされているわけではありません)。
ただし、.net4.0を必要とせずにこの機能を提供しようとするライブラリがいくつかあります。例えばここに。
または、乗数を追跡することで、小さい数字を使用して大きい数字を表すことができます。例えば:
double value = 9;
enum Multiplier {
Hundred,
Thousand,
Million,
Billion,
Trillion
}
現在、値が9であっても、乗数と組み合わせると、9を9兆として効果的に表すことができます(「兆」を入力するか、値の末尾にゼロを追加する何かを書くことで) )。
BigInteger
数字のStringまたはByte []表現を使用するなどのクラス-つまり、実際には2つの「文字列またはバイトとしての数字」を加算および減算する独自のクラスを作成できます-(通常、このタイプのゲームは必要ありませんが、乗算や除算などのより高度な機能もサポートできます)-しかし、メモリ不足になる可能性のある物理的な制限は常に存在することに留意する必要があります。
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。
大きな数字を扱うために、私はヒーローの塔のような良い例だと思うものを見ます。左上隅:
(ソース: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
...
...
そして、大きな数を処理する簡単な方法は、複数の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)にします。
`text`
→ text
)でテキストを折り返すと、コードのチャンク、関数名、データなどに適したモノスペースになります。アンダースコアまたはアスタリスクでテキストを折り返すと、イタリック(_text_
または*text*
→ テキスト)になり、ダブルアンダースコアまたはダブルアスタリスクは太字(__text__
または**text**
→ テキスト)にします。
あなたがすることは、いくつかの変数を組み合わせて、それらの間の追加とオーバーフローを自分で制御することです。そのように任意の数の桁を使用できます。10,000個の32ビット整数を組み合わせると、32,000ビットの数値が必要になります。プログラミング言語に制限はありません。唯一の制限は、把握できるものです。
double
またはをサポートしていない言語/プラットフォームでも同じことが可能ですBigInteger
。