Просто интересно, как такие игры, как Tap titans и Cookie Clicker, справляются с такими большими числами.
Я пытаюсь реализовать пустую игру, однако самый большой числовой формат, поддерживаемый C #, является десятичным.
Я ищу поддержку до 10 ^ 500; это должно быть с плавающей точкой
Как я мог справиться с этим?
PS он должен быть кроссплатформенным, т.е. ПК, Mac, IOS, Android и совместимым с Unity
unity
mathematics
MathHelp
источник
источник
double
. Если бы это был я, я бы использовал BigInteger .Ответы:
Если вы просто хотите хранить огромные числа без полной точности, например, если вы собираетесь показывать 12 567 000 000 000 как 12,567 Т (триллион), вы можете просто использовать стандартные значения с плавающей запятой / десятичные числа и показывать первые x значащих цифр с подходящим суффиксом так. Когда вы находитесь в октиллионах, вам действительно нужно заботиться о каждом отдельном целочисленном приращении?
источник
Вы можете использовать что-то вроде BigInteger , которое доступно только в .net 4.0, если я не ошибаюсь (не поддерживается всеми платформами Unity build).
Однако есть некоторые библиотеки, которые пытаются реализовать эту функциональность без требования .net4.0. Например здесь .
В качестве альтернативы, вы можете использовать меньшие числа для представления большего, отслеживая множитель. Например:
Теперь, даже если у вас есть значение 9, если вы соедините его с вашим множителем, вы можете эффективно представить эти 9 как 9 триллионов (либо введя «триллион», либо написав что-то, что добавит нули в конце вашего значения ).
источник
BigInteger
использование представления числа в виде String или Byte [], могут создать собственный класс, который просто добавляет и вычитает два «числа в виде строк или байтов» ( обычно игра такого типа не в этом нет необходимости, но вы могли бы также поддерживать умножение или деление или другие более продвинутые функции ), но им следует помнить, что всегда существует физический предел, в котором они могут исчерпать память.Вам, вероятно, нужно написать свой собственный класс для использования в Unity, но это не будет особенно сложно.
Внутренне это может быть список целых чисел (например, a
List<int>
), причем каждый элемент в списке соответствует группе из 9 цифр. Каждое целое число будет иметь диапазон от 0 до 999 999 999. Целое число может поддерживать чуть более 2 миллиардов, и вдвое больше, если оно не подписано, но вы захотите иметь переполнение каждой «цифры»1 000 000 000
, потому что вы также захотите чтобы можно было легко преобразовать ваш большой номер в строку для отображения. Проще объединить то, что уже является десятичнойreturn group[i].ToString() + group[i-1].ToString() and so on
цифрой ( ), чем выяснить, как отобразить сумму групп, которые находятся за пределами диапазона любого обычного типа данных.Итак, первый int в вашем списке будет представлять 1s. Следующим будет количество миллиардов. Далее количество квадриллионов и тд.
Сложение и вычитание работали бы так же, как сложение и вычитание ручкой и бумагой, когда вы должны следить за переполнением и переносить его на следующую «цифру», но вместо цифр с диапазоном от 0 до 9 ваши цифры варьируются от От 0 до 999 999 999.
источник
Для обработки больших чисел я бы посмотрел на хороший пример, например, Tower of Hero . Верхний левый угол:
(источник: mzstatic.com )
Не вдаваясь в игровой процесс, способ обработки чисел относительно прост: вы видите две группы чисел. Когда вы поднимаетесь выше в башне и делаете больше «золота», два ведра просто представляют большие числа.
Как только игра проходит T, она перемещается в a, b, c ... z, aa, ab, ...
Делая это таким образом, он по-прежнему позволяет узнать, сколько золота вы «заработали» ... при этом не затягивая игру в деталях.
Вы действительно заботитесь о миллионах, когда ваше число превышает триллионы?
Сохраняет ли оно число в Int, Big Int, Float, Double, Decimal, ...? Custom Array? Когда вы обрабатываете числа таким «нечетким» способом, я не думаю, что это имеет значение ...
Все, что, вероятно, имеет значение, являются наиболее значимыми частями - в данном случае, первыми 6 ... После этого МОГУТ БЫТЬ следующие 3 или 6 - поскольку зарабатывание нескольких сотен К может перерасти в миллионы - но наступает момент, когда можно заработать несколько сотен килограмм не повлияют на вас, когда вы нажмете на T ... намного меньше и больше.
Ваш пробег будет варьироваться (в зависимости от того, что вы хотите / нужно) ... Просто подумал, что я выложу свой 2с на том, что я считаю хорошим / простым примером.
Редактировать:
Дальнейшие размышления о том, как бы я внедрил систему нумерации: у меня был бы номер с 3 значимыми частями: XXXX.YYY (...) xZZZ.
Таким образом, 120.365x1 будет 120k365 ... 120.365x2 будет 120M365K ... и т. Д. Нажмите 4 ведущих (1200.365x2), а затем просто поверните цифры 1.200365 (...) x3. Bam. У вас есть 1B200M.
XY легко поместится в десятичном или плавающем числах ... с Z рядом с ним как int / unsigned int.
С плавающей точкой вы сможете сохранить значительное, но все более неважное количество цифр после точки.
Z будет легко представлять легко понятный блок чисел:
источник
И простой способ обработки больших чисел - это просто иметь более одного значения INTEGER, чем CARRY при любом переполнении. Если у вас есть 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).
Это работает в двоичном тоже. (Те же десятичные значения в двоичном формате) 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 и перенесите его к следующему фрагменту значения (так как вы делаете «сложение и подстановку» с числами по сравнению с реальными двоичными вычислениями).
В идеале вы должны использовать СИМВОЛИЧЕСКУЮ МАТЕМАТУ, которую вы изучили в начальной школе. Как это работает. Если у вас есть десятичный символ 1, и вы добавляете его к 1, тогда вы получаете десятичный символ 2. Причина, по которой я называю это символом, заключается в том, что вы можете использовать любой ряд символов с таблицей поиска «ЕСЛИ символ X (1)» добавляется к символу X (4), затем к выходному символу X (5) ". Символ X (1) может быть изображением кота, а символ X (4) может быть знаком ПРОЦЕНТ, но это не имеет значения. У вас есть ваши символы, основной свод правил того, что происходит, затем эти символы объединяются (что-то вроде таблиц умножения, которые вы запомнили в детстве), и какой символ должен получиться как часть этой операции. С помощью Symbolic Math вы можете добавлять бесконечное количество цифр, при этом никогда не вызывая числовые ограничения вашего процессора.
Один из способов сделать это в простом кодировании состоит в том, чтобы каждая представленная цифра, с которой вы хотите работать, представляла собой единое целое в массиве большого размера. Если вы хотите представить 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).
источник
`text`
→text
) сделает его моноширинным, подходящим для кусков кода, имен функций, данных и т. Д. Обтекание текста подчеркиваниями или звездочками выделит курсивом (_text_
или*text*
→ текст ) и двойными подчеркиваниями или двойными подчеркиваниями. звездочки будут выделены жирным шрифтом (__text__
или**text**
→ текст ).То, что вы делаете, - это объединение нескольких переменных, а затем вы сами контролируете сложение и переполнение. Таким образом, вы можете иметь любое количество цифр. Объедините 10 000 32-битных целых чисел, и у вас получится число с 32 000 бит, если это то, что вам нужно. Нет ограничений в любом языке программирования. Единственное ограничение - это то, что вы можете выяснить.
источник
double
илиBigInteger
.