我有一个字符串,例如"1.5%",想将其转换为double类型的值。
可以通过以下简单方法实现:
public static double FromPercentageString(this string value)
{
return double.Parse(value.SubString(0, value.Length - 1)) / 100;
}
但我不想使用这种解析方法。
还有其他的方法吗,比如使用IFormatProvider或类似的东西?
我有一个字符串,例如"1.5%",想将其转换为double类型的值。
可以通过以下简单方法实现:
public static double FromPercentageString(this string value)
{
return double.Parse(value.SubString(0, value.Length - 1)) / 100;
}
但我不想使用这种解析方法。
还有其他的方法吗,比如使用IFormatProvider或类似的东西?
这是与文化相关的,应该像这样替换:
value = value.Replace(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PercentSymbol, "");
然后解析它。
如果你关心捕获格式错误,我建议使用 TrimEnd 而不是 Replace。Replace会允许格式错误未被检测到。
var num = decimal.Parse( value.TrimEnd( new char[] { '%', ' ' } ) ) / 100M;
这将确保该值必须是一些十进制数字,后面跟着任意数量的空格和百分号,即它至少必须以正确格式的值开头。为了更加精确,您可能希望在“%”上拆分,不删除空条目,然后确保只有两个结果且第二个为空。第一个应该是要转换的值。var pieces = value.Split( '%' );
if (pieces.Length > 2 || !string.IsNullOrEmpty(pieces[1]))
{
... some error handling ...
}
var num = decimal.Parse( pieces[0] ) / 100M;
使用Replace函数将允许您成功地(虽然在我看来不正确地)解析以下内容:
以及1.5%
if (value.EndsWith("%")) ...
。 - Bitterblue稍微好一些,但更少出错的方法:
public static double FromPercentageString(this string value)
{
return double.Parse(value.Replace("%","")) / 100;
}
var result = new Percentage("1.5%");
double d = result.Value;
百分比及其TypeConverter的定义如下:
[TypeConverter(typeof(PercentageConverter))]
public struct Percentage
{
public double Value;
public Percentage( double value )
{
Value = value;
}
public Percentage( string value )
{
var pct = (Percentage) TypeDescriptor.GetConverter(GetType()).ConvertFromString(value);
Value = pct.Value;
}
public override string ToString()
{
return ToString(CultureInfo.InvariantCulture);
}
public string ToString(CultureInfo Culture)
{
return TypeDescriptor.GetConverter(GetType()).ConvertToString(null, Culture, this);
}
}
public class PercentageConverter : TypeConverter
{
static TypeConverter conv = TypeDescriptor.GetConverter(typeof(double));
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return conv.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(Percentage)) {
return true;
}
return conv.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value == null) {
return new Percentage();
}
if (value is string) {
string s = value as string;
s = s.TrimEnd(' ', '\t', '\r', '\n');
var percentage = s.EndsWith(culture.NumberFormat.PercentSymbol);
if (percentage) {
s = s.Substring(0, s.Length - culture.NumberFormat.PercentSymbol.Length);
}
double result = (double) conv.ConvertFromString(s);
if (percentage) {
result /= 100;
}
return new Percentage(result);
}
return new Percentage( (double) conv.ConvertFrom( context, culture, value ));
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (!(value is Percentage)) {
throw new ArgumentNullException("value");
}
var pct = (Percentage) value;
if (destinationType == typeof(string)) {
return conv.ConvertTo( context, culture, pct.Value * 100, destinationType ) + culture.NumberFormat.PercentSymbol;
}
return conv.ConvertTo( context, culture, pct.Value, destinationType );
}
}
static public implicit operator String(Percentage pct) { return pct.ToString(); }
),另一个用于Decimal(因为我已经更改了您原始示例,以使用decimal来获得更好的精度)(static public implicit operator Decimal(Percentage pct) { return pct._value; }
)。 - CARLOS LOTH // Modify a culture so that it has different decimal separators and group separators for numbers and percentages.
var customCulture = new CultureInfo("en-US")
{
NumberFormat = { PercentDecimalSeparator = "PDS", NumberDecimalSeparator = "NDS", PercentGroupSeparator = "PGS", NumberGroupSeparator = "NGS", PercentSymbol = "PS"}
};
// Set the current thread's culture to our custom culture
Thread.CurrentThread.CurrentCulture = customCulture;
// Create a percentage format string from a decimal value
var percentStringCustomCulture = 123.45m.ToString("p");
Console.WriteLine(percentStringCustomCulture); // renders "12PGS345PDS00 PS"
// Now just replace the percent symbol only, and try to parse as a numeric value (as suggested in the other answers)
var deceptiveNumericStringInCustomCulture = percentStringCustomCulture.Replace(customCulture.NumberFormat.PercentSymbol, string.Empty);
// THE FOLLOWING LINE THROWS A FORMATEXCEPTION
var decimalParsedFromDeceptiveNumericStringInCustomCulture = decimal.Parse(deceptiveNumericStringInCustomCulture);
// A better solution...replace the decimal separators and number group separators as well.
var betterNumericStringInCustomCulture = deceptiveNumericStringInCustomCulture.Replace(customCulture.NumberFormat.PercentDecimalSeparator, customCulture.NumberFormat.NumberDecimalSeparator);
// Here we mitigates issues potentially caused by group sizes by replacing the group separator by the empty string
betterNumericStringInCustomCulture = betterNumericStringInCustomCulture.Replace(customCulture.NumberFormat.PercentGroupSeparator, string.Empty);
// The following parse then yields the correct result
var decimalParsedFromBetterNumericStringInCustomCulture = decimal.Parse(betterNumericStringInCustomCulture)/100m;
是的,这段代码有点长,也许我有些迂腐(即使这样的一种文化实际上可能永远不存在)。话虽如此,对我来说,这似乎是一个更通用的解决方案。希望它能帮助到某些人 :)
var num = double.Parse(value.TrimEnd(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PercentSymbol.ToCharArray() ) ) / 100d;
我不确定为什么会有这么多关于字符串替换、转换和转换器的内容。
使用NumberFormat货币部分,但用所需文化中的百分比格式填充它。
// input test value
string value = (.015m).ToString("P", CultureInfo.CurrentCulture);
// set up your format.
double doubleTest;
var numFormat = CultureInfo.CurrentCulture.NumberFormat;
NumberFormatInfo nfi = new NumberFormatInfo()
{
CurrencyDecimalDigits = numFormat.PercentDecimalDigits,
CurrencyDecimalSeparator = numFormat.PercentDecimalSeparator,
CurrencyGroupSeparator = numFormat.PercentGroupSeparator,
CurrencyGroupSizes = numFormat.PercentGroupSizes,
CurrencyNegativePattern = numFormat.PercentNegativePattern,
CurrencyPositivePattern = numFormat.PercentPositivePattern,
CurrencySymbol = numFormat.PercentSymbol
};
// load it.
if (double.TryParse(value, NumberStyles.Currency, nfi, out doubleTest))
{
doubleTest /= 100D;
// use as required.
}
BigDecimal
类中生成百分比格式化值,因为它已经通过利用许多 BCL 功能来生成货币值,所以感谢您的想法! - Mike Marynowski try
{
string str = (string) value;
if ((culture != null) && !string.IsNullOrEmpty(str))
{
str = ((string) value).Trim();
if ((!culture.IsNeutralCulture && (str.Length > 0)) && (culture.NumberFormat != null))
{
switch (culture.NumberFormat.PercentPositivePattern)
{
case 0:
case 1:
if ((str.Length - 1) == str.LastIndexOf(culture.NumberFormat.PercentSymbol, StringComparison.CurrentCultureIgnoreCase))
{
str = str.Substring(0, str.Length - 1);
}
break;
case 2:
if (str.IndexOf(culture.NumberFormat.PercentSymbol, StringComparison.CurrentCultureIgnoreCase) == 0)
{
str = str.Substring(1);
}
break;
}
}
num = Convert.ToDouble(str, culture);
flag = true;
}
}
catch (ArgumentOutOfRangeException)
{
}
catch (ArgumentNullException)
{
}
catch (FormatException)
{
}
catch (OverflowException)
{
}
您可以在Microsoft Connect上为.NET Framework 4的建议投票:扩展double.Parse以解释百分比值
这是一个字符串,无论你如何去掉百分号,你仍然需要将它解析为双精度浮点数。