字符串分数加倍

时间:2012-01-06 17:03:35

标签: c# asp.net string

我需要一个函数来解析用户输入的数字到双精度数。我不能做任何客户端或改变输入的方式。

Input       | Desired Output
"9"         | 9
"9 3/4"     | 9.75
" 9  1/ 2 " | 9.5
"9 .25"     | 9.25
"9,000 1/3" | 9000.33
"1/4"       | .25

我看到了这个post,但是它使用了Python,我只是想知道是否有人知道任何花哨的C#方法来处理这个,然后才花时间写我自己的。

8 个答案:

答案 0 :(得分:5)

我会使用正则表达式:

Regex re = new Regex(@"^\s*(\d+)(\s*\.(\d*)|\s+(\d+)\s*/\s*(\d+))?\s*$");
string str = " 9  1/ 2 ";
Match m = re.Match(str);
double val = m.Groups[1].Success ? double.Parse(m.Groups[1].Value) : 0.0;

if(m.Groups[3].Success) {
    val += double.Parse("0." + m.Groups[3].Value);
} else {
    val += double.Parse(m.Groups[4].Value) / double.Parse(m.Groups[5].Value);
}

尚未测试,但我认为它应该有效。

Here's a demohere's another demo

答案 1 :(得分:3)

BCL中没有任何内容可以做到这一点,但是现有的mathematical expression parsers会有很多(虽然这可能会超过这个特定情况的顶部) )。

自己写一个,因为你发布的有限用例应该不难。

答案 2 :(得分:3)

我看到两个部分。第一个空间之前的所有内容都是整体部分。第一个空格之后的所有内容都是小数部分。将两个部分分开后,您可以从小数部分中删除空格,在/字符上拆分该部分,并将第一部分除以第二部分(如果有第二部分)。然后将结果添加到积分部分以找到答案。

此算法应为每个样本提供正确的结果。对于这样的样本,它可能也会给出错误的结果:“9 .25 / 4”或“9 3/0”,所以这些都是值得关注的。其他的东西包括前导空格,是否要允许其他空格,货币符号,“9.25”(无空格)是否是有效输入,以及如何处理非理性分数,如“1/3”,“1/10”(二元的非理性)等。

对于静态类型的语言,我通常不是测试驱动设计的忠实信徒(你应该先编写测试并进行100%覆盖),但我认为单元测试在某些特定情况下具有价值,并且这是其中一种情况。我会为一些常见和边缘情况组合一些测试,这样你就可以确定无论你最终如何正确处理输入以通过测试。

答案 3 :(得分:2)

以下是我最终使用的内容:

private double ParseDoubleFromString(string num)
{
    //removes multiple spces between characters, cammas, and leading/trailing whitespace
    num = Regex.Replace(num.Replace(",", ""), @"\s+", " ").Trim();
    double d = 0;
    int whole = 0;
    double numerator;
    double denominator;

    //is there a fraction?
    if (num.Contains("/"))
    {
        //is there a space?
        if (num.Contains(" "))
        {
            //seperate the integer and fraction
            int firstspace = num.IndexOf(" ");
            string fraction = num.Substring(firstspace, num.Length - firstspace);
            //set the integer
            whole = int.Parse(num.Substring(0, firstspace));
            //set the numerator and denominator
            numerator = double.Parse(fraction.Split("/".ToCharArray())[0]);
            denominator = double.Parse(fraction.Split("/".ToCharArray())[1]);
        }
        else
        {
            //set the numerator and denominator
            numerator = double.Parse(num.Split("/".ToCharArray())[0]);
            denominator = double.Parse(num.Split("/".ToCharArray())[1]);
        }

        //is it a valid fraction?
        if (denominator != 0)
        {
            d = whole + (numerator / denominator);
        }
    }
    else
    {
        //parse the whole thing
        d = double.Parse(num.Replace(" ", ""));
    }

    return d;
}

答案 4 :(得分:1)

编写一些可以执行此操作的代码看起来并不困难。首先尝试删除所有空格,看看它是否是合法的号码。如果不是,请找到合法的数字(例如“9 3/4”中的9,3,4并进行简单的算术运算:9 + 3/4 = 9.75

答案 5 :(得分:0)

我为这项工作写了这个方法:

private double DoWork(string data)
    {
        double final = 0;

        foreach (string s in data.Split(' '))
        {
            if (s.Contains('/'))
            {
                final += double.Parse(s.Split('/')[0]) / double.Parse(s.Split('/')[1]);
            }
            else
            {
                double tryparse = 0;
                double.TryParse(s, out tryparse);
                final += tryparse;
            }
        }

        return final;
    }

答案 6 :(得分:0)

对你有用吗?

我认为你也可以使用动态编译代码

    static void Main(string[] args)
    {
        var value = "9 3/4";
        value = value.Split(' ')[0] + "d + " + value.Split(' ')[1] + "d";

        var exp = " public class DynamicComputer { public static double Eval() { return " + value + "; }}";

        CodeDomProvider cp = new Microsoft.CSharp.CSharpCodeProvider();
        ICodeCompiler icc = cp.CreateCompiler();
        CompilerParameters cps = new CompilerParameters();
        CompilerResults cres;

        cps.GenerateInMemory = true;

        cres = icc.CompileAssemblyFromSource(cps, exp);

        Assembly asm = cres.CompiledAssembly;

        Type t = asm.GetType("DynamicComputer");

        double d = (double)t.InvokeMember("Eval",
            BindingFlags.InvokeMethod,
            null,
            null,
            null);

        Console.WriteLine(d);

        Console.Read();
    }

答案 7 :(得分:0)

以下解决方案不适用于负分数。可以通过改变

来改进
    //is it a valid fraction?
    if (denominator != 0)
    {
        d = whole + (numerator / denominator);
    }
    to
    //is it a valid fraction?
    if (denominator != .0)
    {
        var sign = Math.Sign(whole);

        d = whole + sign*(numerator/denominator);
    }