Нужна помощь с форматированием BigDouble (unity)
Есть код игры-кликера. По нажатию кнопки, увеличивает значение moneyAmount на moneyPerClick и выводит на экран. Так же есть Апгрейд, при каждой покупке которого, значение upgradePrice и moneyPerClick умножается на multiplier:
private BigDouble moneyAmount;
private BigDouble multiplier = 1.15;
private BigDouble moneyPerClick = 20;
private BigDouble upgradePrice = 50;
public GameObject DisplayValue;
//Добавление денег за клик
public void ClickToCreate()
{
if (!UpgradeMenu.upgradeIsOpen)
{
moneyAmount += moneyPerClick;
DisplayValue.GetComponent<Text>().text = "$: " + FormatMoney(moneyAmount);
}
}
//Покупка апгрейда
public void FirstUpgrade()
{
if (moneyAmount >= upgradePrice)
{
moneyAmount -= upgradePrice;
upgradePrice *= multiplier;
moneyPerClick *= multiplier;
DisplayValue.GetComponent<Text>().text = "$: " + FormatMoney(moneyAmount);
}
}
Ниже есть метод FormatMoney (написанный не мной), и делался он под тип данных decimal.Проблема для меня в том, что в BigDouble значения состоят из двух частей, Мантисса и Экспонента, и значения используются не больше 100(вроде). А метод FormatMoney работает с decimal и делит огромные цифры на 1000, после плюсует префикс из массива в конец числа.
Нужно, чтобы было так: если количество нулей меньше 14-ти, то после числа добавлялись префиксы из массива, если нулей больше 14-ти то BigDouble сам приписывает экспоненту Е+15,Е+16... и т.д.
static string[] names = { "", "K", "M", "B", "T", "A", "Aa", "Ab", "Ac", "Ad", "Ae", "Af", "Ag", "Ah" };
//Форматирование значений и добавление префикса
public static string FormatMoney(decimal value)
{
int n = 0;
while (n + 1 < names.Length && value >= 1000m)
{
value /= 1000m;
n++;
}
if (value <= 1000m)
{
return string.Format("{0}{1}", Math.Round(value, 0), names[n]);
}
else
{
return string.Format("{0}{1}", Math.Round(value, 2), names[n]);
}
}
И ещё хотел бы узнать как округлять значения BigDouble без префикса, потому что там выводит, пример: 1,2658560727854Е+15 и т.д. А нужно так, пример: 1,265Е+15. Round`ом не получается, потому что у BigDouble нет такой перегрузки как в обычном Math, где вторым аргументом указывается число знаков после запятой. Прошу помощи, уже неделю ломаю голову.
Скриншоты:
Значение 1360, а мне нужно 1.36к:

Длина значения увеличивается от значения е. Тут должно быть число 5.400М:

Тут очень длинное значение, мне нужно его как-то сократить до двух-трёх знаков после запятой, т.е должно число должно выглядеть так: 5.400Е+15:

Ответы (1 шт):
Сразу скажу, что я не совсем понял, что вам нужно, но переделал вашу функцию вот таким образом (комментарии ниже):
static int Accuracy = 3; // Точность (чисел после запятой)
static string FormatMoney(decimal value)
{
int n = 0;
while (Math.Abs(value) >= 1000) {
value /= 1000;
n++;
}
// Option 1:
value = Math.Round(value, Accuracy);
// Option 2:
/*
decimal RoundedValue = Math.Round(value, Accuracy);
value = (RoundedValue == (int) RoundedValue ? (int) RoundedValue : RoundedValue);
*/
if (n < names.Length) {
return string.Format("{0}{1}", value, names[n]);
}
else {
n *= 3;
while (Math.Abs(value) >= 10) {
value /= 10;
n++;
}
return string.Format("{0}E+{1}", value, n);
}
}
Скажу сразу, что мне кажется, вы неправильно пытаетесь расставлять суффиксы. Для вас при умножении числа на 10 автоматически берется следующий суффикс, однако каждый суффикс должен продерживаться 3 "поколения":
2000 -> 2K
20000 -> 20K
200000 -> 200K
---
3100000 -> 3.1M
31000000 -> 31M
310000000 -> 310M
Именно таким образом работает мой код.
ВАЖНО: в коде отмечены две опции: Option 1 точно выполняет ваше условие, Option 2 поможет от случаев, когда при округлении до X знаков после запятой, эти знаки - нули. Пример:
2000000003 -> 2.000B (при Option1)
2000000003 -> 2B (при Option2)
ПРИМЕРЫ работы этой функции при Accuracy=3 и на Option1
ВВОД:
0
1
12345
1234567890
12345.6789
10000000000000m
1000000000000000000000000000m
282572562723657m
3000000007
ВЫВОД:
0
1
12.345K
1.235B
12.346K
10T
1E+27
282.573T
3.000B
Если указываете огромные числа напрямую (не decimal переменными), то обязательно добавлять m:
FormatMoney(100000000000000m);
FormatMoney(2825725627236572m);
P.S. Проще была бы функция
FormatMoney, которая бы принимала вашBigDouble, то есть мантиссу и экспоненту. Я делал сdecimal, как было в вопросе.
P.P.S. Я мог неверно понять, что вам нужно. Если это так, пишите в комментариях, я попытаюсь помочь. Если я понял все верно и вы примите ответ, то я удалю
P.P.S.