有没有办法在C#中将字符串转换为十进制但忽略尾随“垃圾”?即像PHP的floatval()
或C strtod()
?
e.g。
将字符串"2974.23abcdefs"
转换为小数2974.23
答案 0 :(得分:0)
正如其他人所提到的那样,对于你在PHP中可以做的事情没有确切的替代,我认为,这是有充分理由的。在Web应用程序的场景中,我不确定如果我最后接受带有垃圾的小数,我实际上想将其视为有效数据,但这只是我的看法。
您可以做的是定义一个捕获小数的正则表达式,并认识到这种情况正在发生。我发现这更安全可靠。
显然,正则表达式可以改进但这只是一个简单的例子: -
var match = Regex.Match("2974.23abcdefs", "^([0-9]+\\.[0-9]+)(.+)?$");
if (match.Success)
{
// See the also the link below for using Decimal.TryParse
Console.WriteLine(Convert.ToDecimal(match.Groups[1].Value));
}
请参阅https://msdn.microsoft.com/en-us/library/system.decimal.tryparse%28v=vs.110%29.aspx了解我转换为小数的首选方法。这将确保您正在处理正则表达式的输出,以了解Decimal的构成方式
有关正则表达式的更多信息,请参阅https://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex%28v=vs.110%29.aspx
答案 1 :(得分:0)
作为 first , second ,第三次尝试,这应该是:
static double Parse(string str, IFormatProvider provider = null)
{
if (str == string.Empty)
{
return 0;
}
if (provider == null)
{
provider = CultureInfo.CurrentCulture;
}
NumberFormatInfo nfi = NumberFormatInfo.GetInstance(provider);
// [ws][sign][integral-digits[,]]integral-digits[.[fractional-digits]][E[sign]exponential-digits][ws]
string ws = @"\s*";
string sign = @"(" + Regex.Escape(nfi.PositiveSign) + "|" + Regex.Escape(nfi.NegativeSign) + ")?";
string integralDigits1 = "([0-9](" + Regex.Escape(nfi.NumberGroupSeparator) + ")*)*";
string integralDigits2 = "[0-9]+";
string fractionalDigits = "(" + Regex.Escape(nfi.NumberDecimalSeparator) + "[0-9]*)?";
string exponentialDigits = "([Ee]" + sign + "[0-9]+)?";
var rx = new Regex(ws + sign + integralDigits1 + integralDigits2 + fractionalDigits + exponentialDigits);
string match = rx.Match(str).ToString();
if (match == string.Empty)
{
return 0;
}
return double.Parse(match, provider);
}
请注意,组合正则表达式非常复杂,因为有各种各样的"部分"在已写入字符串的完整双精度数中。
来自MSDN:
[WS] [符号] [积分位数[,]]积分位数[[小数位] [E [符号]指数位数] [WS]
如果它们太大,还有一些数字会使这个函数崩溃。因此,传递new string('9', 1000)
会使double.Parse
抛出异常。
使用它像:
double num = Parse(" +1,0.1234E+12abcdefgh", CultureInfo.InvariantCulture);
或
double num = Parse(" +1,,,,,0.1234E+12abcdefgh");
(如果您不需要配置文化,请使用CultureInfo.CurrentCulture
)
答案 2 :(得分:0)
这可以工作,但只处理数字和当前文化的小数分隔符:
string input = "2974.23abcdefs";
decimal d;
char decSep = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator[0]; // there is no culture with a decimal-separator that has more than one letter so this isn't harmful
if(!string.IsNullOrEmpty(input) && Char.IsDigit(input[0]))
{
string number = string.Concat(input.TakeWhile(c => Char.IsDigit(c) || decSep == c));
bool validDecimal = decimal.TryParse(number, out d);
Console.WriteLine("Valid? {0} Parsed to: {1}", validDecimal, d);
}
由于我们在德国使用,
作为小数点分隔符,因此我得到的结果与使用.
作为分隔符的人不同。得到2974.23
,我得到2974
。
答案 3 :(得分:0)
有很多方法可以做到这一点。我建议先使用正则表达式,然后使用decimal.TryParse()
。
这是一个正则表达式,它捕获字符串开头的浮点数,如-123.43或仅1234.56或123456:
^([+-][0-9]+\.?[0-9]*).*$
将它放入C#看起来像这样:
// Step 1: Getting some input
String input = "123.4533wefwe";
// Step 2: Get rid of the trail
Regex r = new Regex(@"^([+-][0-9]+\.?[0-9]*).*$", RegexOptions.IgnoreCase);
MatchCollection matches = r.Matches(input);
if (matches.Count > 0) {
Match match = matches[0];
GroupCollection groups = match.Groups;
// Step 3: create a real decimal from the string
decimal i;
NumberStyles style;
CultureInfo culture;
style = NumberStyles.Number;
culture = CultureInfo.CreateSpecificCulture("en-GB");
String matchedNumber = groups[1].Value;
if (decimal.TryParse(matchedNumber, style, culture, out i)) {
// Step 4: giving back the result:
Console.WriteLine("Parsed decimal: " + i);
}
}
这个输出是:
Parsed decimal: 123.4533
备注:如果要解析包含指数表示法的实数浮点数文字,所有这些似乎都会成为一个更大的问题。然后,需要几个阶段的铸造。