减少 C# 中的 BigInteger 值

Reducing a BigInteger value in C#

我对使用 BigIntegers 有点陌生,并尝试了一些方法来让这个系统正常工作,但现在感觉有点卡住了,非常感谢在正确的方向或解决方案上的推动。

我目前正在开发一个系统,该系统将 BigInteger 值减少为更易读的形式,这在我当前的实现中运行良好,但我想进一步扩展它以实现小数。

为了更好地描述我正在尝试的内容,我将对其进行分解。

在这种情况下,我们有一个方法,它接受一个 BigInteger,return将它作为一个字符串:

public static string ShortenBigInt (BigInteger moneyValue)

考虑到这一点,当 10,000 等数字传递给此方法时,10k 将是 return编辑。与 1,000,000 相同,这将 return 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];
     }
 }

该系统的工作原理是从前缀数组中抓取一个字符串,并将数字简化为最简单的形式,然后将两者结合起来,然后 return 在该前缀范围内对其进行处理。

所以在这种情况下,我的问题是: 我怎样才能以同样的方式 return 处理这个问题,其中传递 100,000 会 return 100k,但也会做类似 1,111,111 的事情会 return 1.11M?

目前,通过 1,111,111M returns 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、tsTG、qtTG、QnTG、ssTG、 SpTG、OcTG、NoTG、QdDR、uQDR、dQDR、tQDR、 qdQDR、QnQDR、sxQDR、SpQDR、OQDDr、NQDDr、 qQGNT, uQGNT, dQGNT, tQGNT, qdQGNT, QnQGNT, sxQGNT、SpQGNT、OQQGNT、NQQGNT、SXGNTL

有没有人碰巧知道如何做这样的事情?任何语言都可以,C# 更可取,但我很擅长翻译。提前致谢!

手动格式化可能有点像这样:

(前缀为一个字符串,它是一个 char[])

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";
}

尽管 Falco 的回答 确实 有效,但它不适用于所请求的内容。这是我一直在寻找的解决方案,并从朋友那里得到了一些帮助。此解决方案将持续到您的字符串前缀数组中没有更多前缀为止。如果 运行 越界,将抛出异常并通过返回 "Infinity".

来处理

这个解决方案更好,因为在这个过程中没有 c运行ch 下降到 doubles/decimals。此解决方案没有数量上限,唯一的限制是您 make/provide.

的前缀数量
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";
    }
}