C# 确定double.Parse使用的字符数
这是一个简单的问题,但我找不到任何函数来解决它。我需要一种方法来确定使用了多少个字符来解析字符串中的double 我想取字符串的剩余部分,通过在符号字符串表中进行简单的查找来确定它是什么度量单位C# 确定double.Parse使用的字符数,c#,.net,parsing,C#,.net,Parsing,这是一个简单的问题,但我找不到任何函数来解决它。我需要一种方法来确定使用了多少个字符来解析字符串中的double 我想取字符串的剩余部分,通过在符号字符串表中进行简单的查找来确定它是什么度量单位 更新 我把答案授予了奥利维尔·杰科特·德斯科姆布斯,因为他拥有最完整的正则表达式,并用我自己关于如何使用正则表达式的答案击败了我。我看到的这个答案中唯一的缺陷是没有考虑到不同文化背景下的逗号和点交换(我在我的答案中考虑到了这一点,尽管它看起来有点混乱) 然而,我将要实现的实际解决方案将不会使用正则表达
更新 我把答案授予了奥利维尔·杰科特·德斯科姆布斯,因为他拥有最完整的正则表达式,并用我自己关于如何使用正则表达式的答案击败了我。我看到的这个答案中唯一的缺陷是没有考虑到不同文化背景下的逗号和点交换(我在我的答案中考虑到了这一点,尽管它看起来有点混乱) 然而,我将要实现的实际解决方案将不会使用正则表达式。我仍然给出答案的原因主要是因为我问错了问题。我认为正则表达式的答案是我所问问题的最佳解决方案
我提出的解决方案是迭代可用的单位,并使用
inputStr.EndsWith(unitStr)
与字符串进行比较,当我得到一个正匹配时,我将通过从测试字符串中减去单位字符串的长度立即知道数字的长度,然后我可以使用double.Parse()
(修剪后)保留剩余的内容。我建议您使用正则表达式,如下所示:
(?<double>[\d.]+)(?<unit>.*)
在这里,组
double
将包含“1.25632”,组unit
将包含“meter”我当前的解决方案是使用正则表达式解释浮点值,然后检索长度,以了解单元的起始位置
public static (double Value, string unit) Parse(string value)
{
var result = RegexParseDouble.Match(value);
if(result.Success)
{
return (double.Parse(value.Substring(result.Length)), value.Substring(result.Length));
}
throw new FormatException("Value cannot be parsed as a floating point number.");
}
private static Regex RegexParseDouble
{
get => new Regex(
@"^[-+]?(\d+" +
Thread.CurrentThread.CurrentCulture.NumberFormat.NumberGroupSeparator +
@"\d+)*\d*(" +
Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator +
@")?\d+([eE][-+]?\d+)?");
}
理想情况下,我不希望自己解析字符串,然后让.NET再次解析字符串以提供值。可以让Regex返回匹配项,这样就不需要两次传递
var parseNumUnit = new Regex(
@"(?<num>(\+|-)?([0-9,]+(\.)?[0-9]*|[0-9,]*(\.)?[0-9]+)((e|E)(\+|-)?[0-9]+)?)\s*(?<unit>[a-zA-Z]*)"
);
Match match = parseNumUnit.Match("+13.234e-3m");
string number = match.Groups["num"].Value; // "+13.234e-3"
string unit = match.Groups["unit"].Value; // "m"
var parseNumUnit=new Regex(
@“(?(\+)?([0-9,]+(\)?[0-9]*.[0-9,]*(\)?[0-9]+)((e)(\+)(\+)([0-9]+)\s*([a-zA-Z]*)”
);
Match Match=parsenuminit.Match(“+13.234e-3m”);
字符串编号=匹配。组[“num”]。值;//“+13.234e-3”
字符串单位=匹配。组[“单位”]。值;//“m”
这里
(?表达式)捕获名为“name”的组中的表达式。
我的数字正则表达式非常复杂,允许使用诸如
“+13.234e-3”
,“12.34”
,“.25”
,“10.”或“23503.14”
。如果数字的格式更简单,可以简化正则表达式。一个不涉及正则表达式的简单选项:
var input = "42,666 towels";
// Get a char[] of all numbers or separators (',' or '.', depending on language):
var numericChars = input
.TakeWhile(c => c == ',' || c == '.' || Char.IsNumber(c))
.ToArray();
// Use the chars to init a new string, which can be parsed to a number:
var nr = Double.Parse(new String(numericChars));
// ...and the remaining part of the original string is the unit:
// (Note that we use Trim() to remove any whitespace between the number and the unit)
var unit = input.Substring(numericChars.Count()).Trim();
// Outputs: Nr is 42,666, unit is towels.
Console.WriteLine($"Nr is {nr}, unit is {unit}.");
更新
作为对下面评论的回应,这里有一个扩展。我承认这破坏了上面的一些优雅的简单性,但至少它是可读的、可配置的(可扩展的),并且可以工作:
var nrFormat = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
// Remove or add strings to this list as needed:
var validStrings =
new List<string>{
nrFormat.NaNSymbol,
nrFormat.NegativeSign,
nrFormat.NumberDecimalSeparator,
nrFormat.PercentGroupSeparator,
nrFormat.PercentSymbol,
nrFormat.PerMilleSymbol,
nrFormat.PositiveInfinitySymbol,
nrFormat.PositiveSign
};
validStrings.AddRange(nrFormat.NativeDigits);
validStrings.Add("^");
validStrings.Add("e");
validStrings.Add("E");
validStrings.Add(" ");
// You can use more complex numbers, like:
var input = "-42,666e-3 Towels";
// Get all numbers or separators (',' or '.', depending on language):
var numericChars = input.TakeWhile(c => validStrings.Contains("" + c)).ToArray();
// Use the chars to init a new string, which can be parsed to a number:
var nr = Double.Parse(new String(numericChars));
// ...and the remaining part of the original string is the unit:
// (Note that we use Trim() to remove any whitespace between the number and the unit)
var unit = input.Substring(numericChars.Count()).Trim();
// Outputs is now: "Nr is -0,042666, unit is Towels"
Console.WriteLine($"Nr is {nr}, unit is {unit}.");
var nrFormat=System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
//根据需要将字符串删除或添加到此列表:
var validStrings=
新列表{
nrFormat.NaNSymbol,
nrFormat.NegativeSign,
nrFormat.NumberDecimalSeparator,
nrFormat.PercentGroupSeparator,
nrFormat.PercentSymbol,
nrFormat.PerMilleSymbol,
nrFormat.PositiveInfinitySymbol,
nrFormat.PositiveSign
};
validStrings.AddRange(nrFormat.NativeDigits);
有效字符串。添加(“^”);
有效字符串。添加(“e”);
有效字符串。添加(“E”);
有效字符串。添加(“”);
//您可以使用更复杂的数字,如:
var input=“-42666E-3毛巾”;
//获取所有数字或分隔符(“、”或“”,具体取决于语言):
var numericChars=input.TakeWhile(c=>validStrings.Contains(“+c)).ToArray();
//使用字符初始化新字符串,该字符串可以解析为数字:
var nr=Double.Parse(新字符串(numericChars));
//…原始字符串的剩余部分是单位:
//(请注意,我们使用Trim()删除数字和单位之间的任何空格)
var unit=input.Substring(numericChars.Count()).Trim();
//现在输出为:“Nr为-0042666,单位为毛巾”
WriteLine($“Nr为{Nr},单位为{unit}”);
正如你所看到的,现在的输入可能要复杂得多;您甚至可以使用var input=”之类的内容∞ 花园侏儒”代码>,这将产生奇妙的输出:
Nr为∞, 单位是花园侏儒
我想到了一个非正则表达式的解决方案。如果您可以保证您的输入将始终采用数字空间单位的格式,那么您只需执行以下操作:
public static (double Value, string unit) Parse(string value)
{
var values = value.Split(" ");
double number;
if (!double.TryParse(values[0], out number))
throw new FormatException("Value cannot be parsed as a floating point number.");
string unit = values[1];
return (number, unit);
}
如果您的输入字符串格式是其他格式但保持一致,则可以执行类似的操作以匹配该格式。您似乎是在假设double.parse在double的有效字符用完时停止操作的。我不相信它是这样工作的。您必须事先确定值的结束位置,并将适当的子字符串传递给double.parse。请给出一个示例,说明您希望在C#parse
方法中处理整个输入字符串。在某些情况下,您需要指定参数(例如修剪空白)。它不像在C
中,函数忽略前导空格并在无效字符上停止。好的,如果我使用正则表达式,我也可以找到值的结尾,我将更新我自己的答案以反映这一点。仅作为注释。知道数字的格式总是好的。因此,请在解析方法中指定使用的区域性。如果您知道,它应该是唯一一个带有单位后缀的数字,那么只基于后缀的拆分器可能更好:例如,^(.*)(\s*)([a-zA-Z]+)$
请参见:尽管我可以使用正则表达式将数字作为命名组具体解析出来,但我仍然必须使用double.parse将其转换为实际的double
类型()
或通过取出单个组件并自己构建值。Double.Parse()
var nrFormat = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
// Remove or add strings to this list as needed:
var validStrings =
new List<string>{
nrFormat.NaNSymbol,
nrFormat.NegativeSign,
nrFormat.NumberDecimalSeparator,
nrFormat.PercentGroupSeparator,
nrFormat.PercentSymbol,
nrFormat.PerMilleSymbol,
nrFormat.PositiveInfinitySymbol,
nrFormat.PositiveSign
};
validStrings.AddRange(nrFormat.NativeDigits);
validStrings.Add("^");
validStrings.Add("e");
validStrings.Add("E");
validStrings.Add(" ");
// You can use more complex numbers, like:
var input = "-42,666e-3 Towels";
// Get all numbers or separators (',' or '.', depending on language):
var numericChars = input.TakeWhile(c => validStrings.Contains("" + c)).ToArray();
// Use the chars to init a new string, which can be parsed to a number:
var nr = Double.Parse(new String(numericChars));
// ...and the remaining part of the original string is the unit:
// (Note that we use Trim() to remove any whitespace between the number and the unit)
var unit = input.Substring(numericChars.Count()).Trim();
// Outputs is now: "Nr is -0,042666, unit is Towels"
Console.WriteLine($"Nr is {nr}, unit is {unit}.");
public static (double Value, string unit) Parse(string value)
{
var values = value.Split(" ");
double number;
if (!double.TryParse(values[0], out number))
throw new FormatException("Value cannot be parsed as a floating point number.");
string unit = values[1];
return (number, unit);
}