Уменьшение значения BigInteger в C# - PullRequest
2 голосов
/ 11 февраля 2020

Я немного новичок в работе с BigIntegers и уже пытался кое-что сделать, чтобы эта система работала, но сейчас чувствую себя немного застрявшим и очень ценю толчок в правильном направлении или решение.

В настоящее время я работаю над системой, которая уменьшает значения BigInteger до более удобочитаемой формы, и это прекрасно работает с моей текущей реализацией, но я хотел бы дополнительно расширить ее, чтобы реализовать десятичные дроби.

Чтобы лучше дать представление о том, что я пытаюсь сделать, я разобью его.

В этом контексте у нас есть метод, который берет BigInteger и возвращает его в виде строки:

public static string ShortenBigInt (BigInteger moneyValue)

С учетом этого при передаче этому методу такого числа, как 10000 , будет возвращено 10k . То же самое для 1 000 000 , который будет возвращать 1M .

. Это делается следующим образом:

for(int i = 0; i < prefixes.Length; i++)
{
     if(!(moneyValue >= BigInteger.Pow(10, 3*i)))
     {
         moneyValue = moneyValue / BigInteger.Pow(10, 3*(i-1));

         return moneyValue + prefixes[i-1];
     }
 }

Эта система работает путем захвата строки из массив префиксов и приведение чисел к их простейшим формам, объединение двух и возвращение их внутри этого диапазона префиксов.

Итак, с этим контекстом у меня возникает вопрос: как я могу go вернуть это так же, когда прохождение 100,000 вернуло бы 100k , но при выполнении чего-то вроде 1,111,111 вернулось бы 1,11M ?

В настоящее время передача 1,111,111M возвращает 1M , но я бы хотел, чтобы дополнительные .11 были отмечены. Не более 2 десятичных знаков.

Моя первоначальная мысль заключалась в том, чтобы преобразовать большое целое число в строку, затем разбить первые несколько символов на новую строку и разобрать там десятичную дробь, но поскольку префиксы не меняются до тех пор, пока значения не достигнут своей 1000-й отметки, будет сложнее определить, когда ставить десятичное число.

Моя следующая мысль заключалась в использовании BigInteger.Log, чтобы уменьшить значение до десятичного дружественного числа и выполнить простое деление, чтобы получить значение в десятичной форме, но выполнение этого, похоже, не сработало с моей реализацией.

Эта система должна динамически работать для следующих префиксов:

k, M, B , T, qd, Qn, sx, Sp, O, N, de, Ud, DD, tdD, qdD, QnD, sxD, SpD, OcD, NvD, Vgn, UVg, DVg, TVg, qtV, QnV, SeV , SPG, OVG, NVG, TGN, UTG, DTG, tTT, qtTG, QnTG, ssTG, SpTG, OcTG, NoTG, QdDR, uQDR, dQDR, tQDR, qdQDR, QnQDR, sxQDR, SpQDR, OQDGR , dQGNT, tQGNT, qdQGNT, QnQGNT, sxQGNT, SpQGNT, OQQGNT, NQQGNT, SXGNTL

Wo Может кто-нибудь знает, как сделать что-то подобное? Любой язык в порядке, C# предпочтительнее, но у меня все хорошо с переводом. Заранее спасибо!

Ответы [ 2 ]

3 голосов
/ 11 февраля 2020

форматирование вручную может работать примерно так:

(префиксы в виде строки, которая является символом [])

public static string ShortenBigInt(BigInteger moneyValue)
{
    string prefixes = " kMGTP";
    double m2 = (double)moneyValue;

    for (int i = 1; i < prefixes.Length; i++)
    {
        var step = Math.Pow(10, 3 * i);
        if (m2 / step < 1000)
        {
            return String.Format("{0:F2}", (m2/step)) + prefixes[i];    
        }
    }
    return "err";
}
0 голосов
/ 13 февраля 2020

Хотя ответ Falco работает , он не работает для того, что было запрошено. Это было решение, которое я искал и получил помощь от друга. Это решение будет go до тех пор, пока в вашем строковом массиве префиксов не останется префиксов. Если вы исчерпаете границы, исключение будет сгенерировано и обработано возвращением «Бесконечности».

Это решение лучше из-за того, что в этом процессе нет сокращения до двойных / десятичных дробей. В этом решении нет ограничения числа, единственным ограничением является количество префиксов, которые вы делаете / предоставляете.

public static string ShortenBigInt(BigInteger moneyValue)
{
    if (moneyValue < 1000)
        return "" + moneyValue;

    try
    {
        string moneyAsString = moneyValue.ToString();
        string prefix = prefixes[(moneyAsString.Length - 1) / 3];

        BigInteger chopAmmount = (moneyAsString.Length - 1) % 3 + 1;

        int insertPoint = (int)chopAmmount;

        chopAmmount += 2;

        moneyAsString = moneyAsString.Remove(Math.Min(moneyAsString.Length - 1, (int)chopAmmount));
        moneyAsString = moneyAsString.Insert(insertPoint, ".");

        return moneyAsString + " " + prefix;
    }
    catch (Exception exceptionToBeThrown)
    {   
        return "Infinity";
    }
}
...