闲置游戏如何处理如此大量的数字?


31

只是想知道Tap titans和Cookie Clicker之类的游戏如何处理这么大的数字。

我正在尝试实现一个空闲游戏,但是C#支持的最大数字格式是十进制。

我希望最多支持10 ^ 500;需要浮点数

我该如何处理?

PS它需要跨平台,即PC,Mac,iOS,Android,并与Unity兼容


2
如果我没记错的话,您可以访问Cookie Clicker的代码,因此您可以检查一下...
Vaillancourt

不,我已经阻止了Cookie Clicker!
Arturo TorresSánchez16年

2
我看过Unity游戏TimeClickers的反编译源代码。他们只是使用double。如果是我,我会使用BigInteger
BlueRaja-Danny Pflughoeft

1
@VioletGiraffe:我有点同意,我想让我的(我们的)疑问具体化(以帮助OP弄清楚问题):关于这个问题,什么是“闲置游戏”(这使得这种情况成为可能)游戏是大数的特殊情况)?“ 这么大的数字”(本人重点关注)指的是哪种数字?您希望数字多大
OR Mapper

您总是可以将这么多的数字存储在字符串中,并轻松实现一个函数来对字符串求和。
dev-masih

Answers:


40

如果您只想存储没有完全准确性的海数,例如,如果要显示12,567,000,000,000为12.567T(万亿),则可以使用标准的float / decimal值并显示前x个有效数字,并带有合适的后缀像这样。当达到八十亿时,您真的需要关心每个整数增量吗?


4
这实际上可能是最明智的答案,而且我可以肯定Cookie Clicker只是在JavaScript中使用了标准的float-例如,当我“入侵”它时(阅读:弄乱了控制台),当数字达到1e308时,它就跳了到“ Infinity”,我可以继续购买任何我想要的XD
Niet the Dark Absol

1
大!文本跳转到“ Infinity”这一事实感觉就像开发人员也在防御这种可能发生的事情。同样,简单为王。
罗斯·泰勒·特纳

19
@RossTurner-使它显示文本“ Infinity”可能不涉及任何编码-Infinity只是float可以具有的值,JavaScript知道如何显示它,就像许多其他语言一样。
Jibb Smart 2016年

标准浮点数(双精度,8字节)将不允许代表原始问题要求的最大10 ^ 500的数字,它将达到〜10 ^ 300。如果这还不够的话,应该使用四精度浮点数,根据语言的不同,浮点数可能并不重要。
彼得尼斯(Peteris)2016年

1
每个程序员都应该知道的有关浮点数的知识:float-point-gui.de
史蒂夫(Steve)

20

您可以使用BigInteger之类的东西,如果我没有记错的话,它仅在.net 4.0中可用(并非所有统一构建平台都支持)。

There are some libraries that attempt to bring this functionality without the requirement of .net4.0 however. For example here.

Alternatively, you can use smaller numbers to represent a larger one, by keeping track of the multiplier. For example:

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

Now, even though you have a value of 9, if you couple it with your multiplier, you can effectively represent that 9 as 9 trillion (Either by putting in "trillion" or writing something that will append the zeros at the end of your value).


It is worth noting that classes such as BigInteger use a String or Byte[] representation of the number - so in effect one could create their own class which just adds and subtracts two "numbers as Strings or Bytes" - (usually this type of game doesn't need it but you could support multiplication or division or other more advanced functions as well) - but they'd have to keep in mind that there is always a physical limit where they may run out of memory.
DoubleDouble

1
Each byte multiplies the size of your number by 256. If you run out of memory trying to represent a number, your number didn't have any real value anyway. 256^(2 billion) = 2^8^(2 billion) = 2^(16 billion) ~= 10^(5 billion) (wolframalpha broke trying to make that last conversion). You can specify individual Planck volumes in the observable universe using like 150 digits (<500 bits).
MichaelS

11

You'd likely need to write your own class for use in Unity, but it wouldn't be particularly hard.

Internally, it could be a list of integers (such as a List<int>), with each element in the list corresponding to a group of 9 digits. Each integer would have a range of 0 to 999 999 999. An integer can support a little over 2 billion, and double that if it's unsigned, but you'll want to have each "digit" overflow at 1 000 000 000, because you'll also want to be able to easily convert your big-number into a string for display. It's easier to concatenate what are already decimal digits (return group[i].ToString() + group[i-1].ToString() and so on) than to figure out how to display the sum of groups that are outside of the range of any regular data type.

So, the first int in your list would represent 1s. The next would be the number of billions. The next, the number of quadrillions, and so on.

加法和减法的工作原理就像笔和纸的加法和减法一样,在这里您必须注意溢出情况并将其延续到下一个“数字”,但是您的数字范围是0到9,而不是数字范围为0到9的数字。 0至999999999。


10

对于处理大量数字,我将看一下我认为是一个很好的例子,例如《英雄之塔》。左上角:

1

2
(来源:mzstatic.com

在不玩游戏的情况下,它处理数字的方式相对简单:您会看到两个数字桶。当您在塔楼中爬得更高并且制作更多的“金”时,这两个铲斗只是代表更大的数字。

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不会影响您……更不用说aa或更高。

您的里程会有所不同(取决于您想要/需要的东西)...只是以为我会以我认为是一个好/简单的例子来介绍我的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。am 您有1B200M。

XY很容易放入十进制或浮点数中,而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),并且想要更多,请连续使用两个16位INT值。可以将其视为具有BYTE值(0到255),但只能使用不超过99位的值。一旦达到100,则将其翻转到下一个更高的BYTE值,并找到您认为有用的位数。在当今的GHZ计算机上,即使像这样的草率编码也可以。

当然,还有另一种方法可以更快一些。
如果将数字重复加18,则更快地简单地减去2并加20。18、36、54、72、90、108,... 18 = 20 +(-2)。
它也适用于Binary。(二进制中相同的十进制值)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位十进制限制(0到9999),那么您要做的就是当该值超过9999限制时,从中减去9999并将其带入下一个值块(因为您基本上是在用数字与真实的二进制计算进行“加和减”)。

理想情况下,您只使用在小学学习的SYMBOLIC MATH。这是如何运作的。如果您使用十进制符号1并将其添加到1,那么您将得到十进制符号2。我将此符号称为符号是因为您可以将任何符号系列与“ IF符号X(1)”的查找表一起使用被添加到符号X(4),然后输出符号X(5)”。符号X(1)可以是猫的图片,符号X(4)可以是百分号,但这并不重要。您有自己的符号,这是将要发生的事情的基本规则手册,然后将这些符号组合起来(有点像您记忆中的乘法表),以及作为该操作一部分必须生成的符号。通过使用符号数学,您可以添加无限数量的数字,而无需真正调用处理器的数字限制。

轻松编码的一种方法是,将希望使用的每个表示的数字作为一个单独的单元放置在大尺寸数组中。如果要表示4096个十进制数字(每个单位框不超过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表示大喊大叫
Slipp D. Thompson

5
嘿@Gridlock,我刚刚注意到您是一个全新的用户,欢迎您。我应该澄清我的不赞成票不是永久性的;它旨在作为建设性的批评。您提供的答案很有价值,一旦您完成我要的更正,我将非常乐意将其更改为upvote。另外,请记住,SE不是论坛。一个好的答案不会被阅读,然后被遗忘,而是随着时间的流逝而代表销售代表。在这里和那里修改您的答案有助于社区和您的代表。我希望我不会吓到你。再次欢迎您,我希望您会使用我的建议。
Slipp D. Thompson

1
我将提供的另一个建议是使用一些基本的Markdown格式而不是全大写。用反引号(`text`text)包裹文本可以使其等宽,以适合代码,函数名,数据等的大块。用下划线或星号包裹文本将使其为斜体(_text_*text*文本),并使用双下划线或双星号将使其变为粗体(__text__**text**文本)。
Slipp D. Thompson

0

What you do is have several variables combined, and then you control the addition and overflow between them yourself. You can have any number of digits that way. Combine 10,000 32-bit integers, and you have a number with 32,000 bits, if that is what you need. There is no limit in any programming language. The only limit is what you are able to figure out.


For those that gave downvotes, could you explain why? Even if this is not a popular solution, or one that requires zero effort, it's still a solution, and one that could allow you to do the same even on languages/platforms that do not support double or BigInteger.
TomTsagk
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.