我需要一个函数来解析用户输入的数字到双精度数。我不能做任何客户端或改变输入的方式。
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#方法来处理这个,然后才花时间写我自己的。
答案 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);
}
尚未测试,但我认为它应该有效。
答案 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);
}