C# 解析末尾带有M或B的字符串双精度

C# 解析末尾带有M或B的字符串双精度,c#,C#,是否有一种解析方法可以理解,例如: 1,250,000 = 1.25M 10,000,000 = 10M 10,500,000 = 10.5M 47,600,000,000 = 47.6B 换句话说,我需要将47.6B解析为一个double。我知道我可以手工完成,我想知道是否有直接的方法,比如说使用IFormatter?不,在.Net framework中没有这样的方法(也没有相反的方法可以格式化这样的值) 您需要找到执行此操作的库或自己编写方法 请注意,K/M可能意味着2^10/2^20或1

是否有一种解析方法可以理解,例如:

1,250,000 = 1.25M
10,000,000 = 10M
10,500,000 = 10.5M
47,600,000,000 = 47.6B

换句话说,我需要将47.6B解析为一个double。我知道我可以手工完成,我想知道是否有直接的方法,比如说使用
IFormatter

不,在.Net framework中没有这样的方法(也没有相反的方法可以格式化这样的值)

您需要找到执行此操作的库或自己编写方法


请注意,K/M可能意味着2^10/2^20或10^3/10^6,并且可能是特定于语言的(正如您从
CultureInfo.NumberFormat
信息中看到的那样,.Net framework中也不存在此信息)

此处的一些代码可以修改:

只需指定您自己认可的十进制“收缩”单位列表:

在解析器中使用
double
,或者根据需要将
decimal
转换为
double


使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统线程;
名称空间测试仪
{
公共类FileSizeConverter
{
私有静态系统.Globalization.NumberFormatInfo numberFormat;
私有静态字典知识;
静态FileSizeConverter()
{
/*  
//基本2/二进制“计算机”单元
knownUnits=新词典
{ 
{“”,1L},//没有一个单元与单元B(yte)相同
{“B”,1L},
{“KB”,1024L},
{“MB”,1024L*1024L},
{“GB”,1024L*1024L*1024L},
{“TB”,1024L*1024L*1024L*1024L}
//根据需要填充其余部分
};
*/
//十进制“收缩”单位
knownUnits=新词典
{
{“,1L},
{“M”,1000L*1000L},//百万
{“B”,1000L*1000L*1000L}//10亿(美国)
//根据需要填充其余部分
};
numberFormat=System.Globalization.CultureInfo.CurrentCulture.numberFormat;
}
公共十进制解析(字符串值)
{
//忽略实际值周围的空格
value=value.Trim();
字符串单位=提取单位(值);
string sizeAsString=value.Substring(0,value.Length-unit.Length).Trim();//修剪空格
长乘法器=乘法器或单位(单位);
十进制大小;
if(!decimal.TryParse(sizeAsString,System.Globalization.NumberStyles.Number,numberFormat,out size))
抛出新的ArgumentException(“非法数字”、“值”);
返回乘法器*大小;
}
私有布尔IsDigit(字符值)
{
//我们不想使用char.IsDigit,因为它可以接受深奥的unicode数字
如果(值<'0')返回false;
如果(值>'9')返回false;
返回true;
}
专用字符串提取单元(字符串大小为单位)
{
//从右开始,在第一位结束
int lastChar=sizewishunit.Length-1;
int unitLength=0;

虽然(unitLength)没有直接的方法可以做到这一点,但您可以使用
switch…case
创建自定义方法来确定数字后缀(取决于特定的区域性和基数,例如基数2或基数10),并将其转换为
double
decimal
,如果您有舍入问题,则更推荐)。
   static FileSizeConverter()
   {
        // decimal "contraction" units 

        knownUnits = new Dictionary<string, long>
        {
            { "", 1L },
            { "M", 1000L * 1000L }, // million
            { "B", 1000L * 1000L * 1000L } // billion (usa)
            // fill rest as needed
        };

        numberFormat = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
    }
    var converter = new FileSizeConverter();
    Console.WriteLine(converter.Parse("1.25M"));
    Console.WriteLine(converter.Parse("10M"));
    Console.WriteLine(converter.Parse("10.5M"));
    Console.WriteLine(converter.Parse("47.6B"));
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Rextester
{

    public class FileSizeConverter
    {
        private static System.Globalization.NumberFormatInfo numberFormat;
        private static Dictionary<string, long> knownUnits;

        static FileSizeConverter()
        {
            /*  

            // base2/binary "computer" units

            knownUnits = new Dictionary<string, long>
            { 
                { "", 1L },                                 // no unit is same as unit B(yte)
                { "B", 1L },
                { "KB", 1024L },
                { "MB", 1024L * 1024L},
                { "GB", 1024L * 1024L * 1024L},
                { "TB", 1024L * 1024L * 1024L * 1024L}
                // fill rest as needed
            };

            */

            // decimal "contraction" units 

            knownUnits = new Dictionary<string, long>
            {
                { "", 1L },
                { "M", 1000L * 1000L }, // million
                { "B", 1000L * 1000L * 1000L } // billion (usa)
                // fill rest as needed
            };

            numberFormat = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
        }

        public decimal Parse(string value)
        {
            // ignore spaces around the actual value
            value = value.Trim();

            string unit = ExtractUnit(value);
            string sizeAsString = value.Substring(0, value.Length - unit.Length).Trim();  // trim spaces

            long multiplicator = MultiplicatorForUnit(unit);
            decimal size;

            if (!decimal.TryParse(sizeAsString, System.Globalization.NumberStyles.Number, numberFormat, out size))
                throw new ArgumentException("illegal number", "value");

            return multiplicator * size;
        }

        private bool IsDigit(char value)
        {
            // we don't want to use char.IsDigit since it would accept esoterical unicode digits
            if (value < '0') return false;
            if (value > '9') return false;

            return true;
        }

        private string ExtractUnit(string sizeWithUnit)
        {
            // start right, end at the first digit
            int lastChar = sizeWithUnit.Length - 1;
            int unitLength = 0;

            while (unitLength <= lastChar
                && sizeWithUnit[lastChar - unitLength] != ' '       // stop when a space
                && !IsDigit(sizeWithUnit[lastChar - unitLength]))   // or digit is found
            {
                unitLength++;
            }

            return sizeWithUnit.Substring(sizeWithUnit.Length - unitLength).ToUpperInvariant();
        }

        private long MultiplicatorForUnit(string unit)
        {
            unit = unit.ToUpperInvariant();

            if (!knownUnits.ContainsKey(unit))
                throw new ArgumentException("illegal or unknown unit", "unit");

            return knownUnits[unit];
        }
    }

    public class Program
    {
        public static void Main(string[] paramList)
        {
            var converter = new FileSizeConverter();
            Console.WriteLine(converter.Parse("1.25M"));
            Console.WriteLine(converter.Parse("10M"));
            Console.WriteLine(converter.Parse("10.5M"));
            Console.WriteLine(converter.Parse("47.6B"));
        }
    }
}