繁体   English   中英

在 C# 中格式化大数字

[英]Formatting large numbers in C#

我正在使用 Unity 制作一个“增量游戏”,也称为“空闲游戏”,我正在尝试格式化大量数字。 例如,当gold表示 1000 或更多时,它将显示为Gold: 1k而不是Gold: 1000

using UnityEngine;
using System.Collections;

public class Click : MonoBehaviour {

    public UnityEngine.UI.Text GoldDisplay;
    public UnityEngine.UI.Text GPC;
    public double gold = 0.0;
    public int gpc = 1;

    void Update(){
        GoldDisplay.text = "Gold: " +  gold.ToString ("#,#");
        //Following is attempt at changing 10,000,000 to 10.0M
        if (gold >= 10000000) {
        GoldDisplay.text = "Gold: " + gold.ToString ("#,#M");
        }
        GPC.text = "GPC: " + gpc;
    }

    public void Clicked(){
            gold += gpc;
    }
}

我在网上搜索的时候也试过其他的例子,就是gold.ToString ("#,#"); 来自,但是他们都没有工作。

轻微重构:

public static string KMBMaker( double num )
{
    double numStr;
    string suffix;
    if( num < 1000d )
    {
        numStr = num;
        suffix = "";
    }
    else if( num < 1000000d )
    {
        numStr = num/1000d;
        suffix = "K";
    }
    else if( num < 1000000000d )
    {
        numStr = num/1000000d;
        suffix = "M";
    }
    else
    {
        numStr = num/1000000000d;
        suffix = "B";
    }
    return numStr.ToString() + suffix;
}

用:

GoldDisplay.text = KMBMaker(gold);

变化:

  1. 显式使用double常量
  2. 删除重复
  3. 单独的关注点 - 这种方法不需要了解文本框

我认为没有内置的方法,所以我可能会通过编写自己的方式重新发明轮子,但这应该是我可能会这样做的方式

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            for (double i = 500d; i < 5e23; i *= 100d)
            {
                Console.WriteLine(i.ToMyNumber());
            }

            Console.Read();
        }

    }

    public static class helper
    {
        private static readonly  List<string> myNum;

        static helper()
        {
            myNum = new List<string>();
            myNum.Add("");
            myNum.Add("kilo");
            myNum.Add("mill");
            myNum.Add("bill");
            myNum.Add("tril");
            myNum.Add("quad");
            myNum.Add("quin");
            myNum.Add("sext");
            // ....
        }

        public static string ToMyNumber(this double value)
        {
            string initValue = value.ToString();
            int num = 0;
            while (value >= 1000d)
            {
                num++;
                value /= 1000d;
            }

            return string.Format("{0} {1} ({2})", value, myNum[num], initValue);
        }
    }
}

打印这个

500  (500)
50 kilo (50000)
5 mill (5000000)
500 mill (500000000)
50 bill (50000000000)
5 tril (5000000000000)
500 tril (500000000000000)
50 quad (5E+16)
5 quin (5E+18)
500 quin (5E+20)
50 sext (5E+22)

我在我的项目中使用这种方法,你也可以使用。 也许有更好的方法,我不知道。

public void KMBMaker( Text txt, double num )
    {
        if( num < 1000 )
        {
            double numStr = num;
            txt.text = numStr.ToString() + "";
        }
        else if( num < 1000000 )
        {
            double numStr = num/1000;
            txt.text = numStr.ToString() + "K";
        }
        else if( num < 1000000000 )
        {
            double numStr = num/1000000;
            txt.text = numStr.ToString() + "M";
        }
        else
        {
            double numStr = num/1000000000;
            txt.text = numStr.ToString() + "B";
        }
    }

并在这样的更新中使用此方法。

void Update()
{
     KMBMaker( GoldDisplay.text, gold );
}

我用这个:

    private static List<string> nFormat= new List<string>();

        void Awake()
        {
         nFormat.Add("");
         nFormat.Add("K");
         nFormat.Add("M");
         nFormat.Add("B");
        //...
        }

        public static string Double2dec(double value)
        {
             int num = 0;
             while (value >= 1000d)
             {
                 num++;
                 value /= 1000d;
             }
             return value.ToString("F2") + nFormat[num];
        }

我尝试了这里给出的一些解决方案,但由于需要写下从 K 到 NoNod 的所有缩写而被推迟,所以我写了这个 - 尽管我没有尝试过它是否会极大地影响性能(尽管它似乎像使用科学记数法一样顺利工作)。

using System;
//System.Numerics necessary for us of BigInteger only - alternatively use double (which might be faster, but more inaccurate
using System.Numerics;

namespace WPF_Clicker
{
    public static class NumberFormatter
    {
        
        /*NumberFormat
         * Scientific   => 0.0e0 | example: 1.234e14    -> 123,400,000,000,000
         * Abbreviation  => 0.0xx | example: 123.4T      -> 123,400,000,000,000
        */
        public enum NumberFormat
        {
            Scientific,
            Abbreviation
        }
        
        public static string FormatNumber(BigInteger number, NumberFormat format = NumberFormat.Scientific)
        {
            if (format == NumberFormat.Scientific)
                return ScientificFomat(number);
            else
                return AbbreviationFormat(number);
        }

        public static string ScientificFomat(BigInteger number)
        {
            if (number < 1000)
                //if number smaller than 1,000, don't use special format
                return number.ToString("#.##0");
            else
                //return number as scientific notation with 1 place before and 3 places after decimal point
                return number.ToString("e3");
        }

        public static string AbbreviationFormat(BigInteger number)
        {
            if (number < 1000)
                //if number smaller than 1,000, don't use special format
                return number.ToString("#.##0");

            //get division of number (string length - 1) by 3 and get remainder -> appendix changes with every 4 characters
            int decider = Math.DivRem(number.ToString().Length - 1, 3, out int remainder) - 1;
            //if decider is bigger than 9, looping for every place of the decider number
            int declength = decider.ToString().Length;
            //string is necessary to decide on which appendix to use
            string decstring = decider.ToString();
            //string for the appendix
            string appendix = "";

            if (decider > 99)
                //return "infinity" if decider is greater than 99
                //can be changed if you decide to go over NoNod (decider > 99)
                return "infinity";
            else
            {
                //thousands, millions and billions are special cases
                if (decider < 3)
                {
                    if (decider == 0)
                        appendix = "K";
                    else if (decider == 1)
                        appendix = "M";
                    else if (decider == 2)
                        appendix = "B";
                    else
                        appendix = "";
                }
                else
                    //loop through for decider number string
                    //start at the last place, since these will be definite and it saves the check of whether there is more than 1 place in the decider number string
                    for (int counter = declength - 1; counter >= 0; counter--)
                    {
                        char decchar = decstring[counter];

                        //handle last place of decider number string
                        if (counter == declength - 1)
                            if (decchar == '1')
                                appendix = "U";
                            else if (decchar == '2')
                                appendix = "D";
                            else if (decchar == '3')
                                appendix = "T";
                            else if (decchar == '4')
                                appendix = "Qa";
                            else if (decchar == '5')
                                appendix = "Qi";
                            else if (decchar == '6')
                                appendix = "Sx";
                            else if (decchar == '7')
                                appendix = "Sp";
                            else if (decchar == '8')
                                appendix = "Oc";
                            else if (decchar == '9')
                                appendix = "No";
                            else
                                appendix = "";
                        else
                        //handles second place (or higher) of decider number string
                        {
                            if (decchar == '1')
                                appendix += "Dc";
                            else if (decchar == '2')
                                appendix += "Vg";
                            else if (decchar == '3')
                                appendix += "Td";
                            else if (decchar == '4')
                                appendix += "Qad";
                            else if (decchar == '5')
                                appendix += "Qid";
                            else if (decchar == '6')
                                appendix += "Sxd";
                            else if (decchar == '7')
                                appendix += "Spd";
                            else if (decchar == '8')
                                appendix += "Ocd";
                            else if (decchar == '9')
                                appendix += "Nod";
                        }
                    }

                //since the number string is at this point definitly more than 3 places long, use the remainder to set the decimal point
                string numberstr = number.ToString().Substring(0, 4).Insert(remainder + 1, ",");

                //put the number with decimal point together with the appendix | example: 123,456,789,012,345,678,901,234,567,890,123,456,789,012 -> 123,4DDc
                return numberstr + appendix;
            }
        }
    }
}

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM