字符串分数加倍

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

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 

我看过这篇文章 ,但它使用了Python,我只是想知道在我花时间编写自己的文章之前是否有人知道任何花哨的C#处理方法。

我会使用正则表达式:

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

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

这是一个演示 , 这是另一个演示 。

BCL中没有任何东西可以做到这一点,但是有很多现有的数学 表达式 解析器 (尽管这可能在这种特定情况下可能超过顶部)。

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

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

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

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

这是我最终使用的内容:

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

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

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

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

对你有用吗?

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

  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(); } 

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

  //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); }