应用程序处理表示来自不同区域性的小数的字符串。例如,“1.1”和“1,1”是相同的值。我玩了Decimal.TryParse标志组合,但不能达到我想要的结果。“1,1”变成了“11”或“0”毕竟。有没有可能在一行代码中将这样的字符串转换为十进制,而不预先将“,”char替换为“.”或使用NumberFormat.NumberDecimalSeparator?你怎么处理这种情况?在此先谢谢您!
Decimal.TryParse
NumberFormat.NumberDecimalSeparator
mwg9r5ms1#
您可以创建一个临时CultureInfo对象,以便在解析时使用。
CultureInfo
// get a temporary culture (clone) to modifyvar ci = CultureInfo.InvariantCulture.Clone() as CultureInfo;ci.NumberFormat.NumberDecimalSeparator = ",";decimal number = decimal.Parse("1,1", ci); // 1.1
// get a temporary culture (clone) to modify
var ci = CultureInfo.InvariantCulture.Clone() as CultureInfo;
ci.NumberFormat.NumberDecimalSeparator = ",";
decimal number = decimal.Parse("1,1", ci); // 1.1
字符串
cgfeq70w2#
我找到了另一种方法。看起来很奇怪,但对我来说很有效。因此,如果您不了解目标系统的文化,也不知道将获得哪个值,例如12.33或12,33,您可以执行以下操作
string amount = "12.33";// or i.e. string amount = "12,33";var c = System.Threading.Thread.CurrentThread.CurrentCulture;var s = c.NumberFormat.CurrencyDecimalSeparator;amount = amount.Replace(",", s);amount = amount.Replace(".", s);decimal transactionAmount = Convert.ToDecimal(amount);
string amount = "12.33";
// or i.e. string amount = "12,33";
var c = System.Threading.Thread.CurrentThread.CurrentCulture;
var s = c.NumberFormat.CurrencyDecimalSeparator;
amount = amount.Replace(",", s);
amount = amount.Replace(".", s);
decimal transactionAmount = Convert.ToDecimal(amount);
gg0vcinb3#
您只需要在调用Parse时设置正确的区域性,如下所示:
Parse
string s = "11,20";decimal c1 = decimal.Parse(s, new CultureInfo("fr-FR"));decimal c2 = decimal.Parse(s, new CultureInfo("en-AU"));Console.WriteLine(c1);Console.WriteLine(c2);
string s = "11,20";
decimal c1 = decimal.Parse(s, new CultureInfo("fr-FR"));
decimal c2 = decimal.Parse(s, new CultureInfo("en-AU"));
Console.WriteLine(c1);
Console.WriteLine(c2);
50pmv0ei4#
您有以下可能性:1.你知道文化1.使用计算机已安装的当前区域性设置1.让用户决定在程序中设置其区域性->用户设置1.你不了解文化1.你必须做出决定:你必须定义并记录你的决定1.猜测:你试着解析,试着解析,试着……直到你得到有效的数字
ufj5ltwl5#
下面是我的实现,有什么好主意吗?
/// <summary>/// /// </summary>public static class NumberExtensions{ /// <summary> /// Convert string value to decimal ignore the culture. /// </summary> /// <param name="value">The value.</param> /// <returns>Decimal value.</returns> public static decimal ToDecimal ( this string value ) { decimal number; string tempValue = value; var punctuation = value.Where ( x => char.IsPunctuation ( x ) ).Distinct ( ); int count = punctuation.Count ( ); NumberFormatInfo format = CultureInfo.InvariantCulture.NumberFormat; switch ( count ) { case 0: break; case 1: tempValue = value.Replace ( ",", "." ); break; case 2: if ( punctuation.ElementAt ( 0 ) == '.' ) tempValue = value.SwapChar ( '.', ',' ); break; default: throw new InvalidCastException ( ); } number = decimal.Parse ( tempValue, format ); return number; } /// <summary> /// Swaps the char. /// </summary> /// <param name="value">The value.</param> /// <param name="from">From.</param> /// <param name="to">To.</param> /// <returns></returns> public static string SwapChar ( this string value, char from, char to ) { if ( value == null ) throw new ArgumentNullException ( "value" ); StringBuilder builder = new StringBuilder ( ); foreach ( var item in value ) { char c = item; if ( c == from ) c = to; else if ( c == to ) c = from; builder.Append ( c ); } return builder.ToString ( ); }}[TestClass]public class NumberTest{ /// <summary> /// /// </summary> [TestMethod] public void Convert_To_Decimal_Test ( ) { string v1 = "123.4"; string v2 = "123,4"; string v3 = "1,234.5"; string v4 = "1.234,5"; string v5 = "123"; string v6 = "1,234,567.89"; string v7 = "1.234.567,89"; decimal a1 = v1.ToDecimal ( ); decimal a2 = v2.ToDecimal ( ); decimal a3 = v3.ToDecimal ( ); decimal a4 = v4.ToDecimal ( ); decimal a5 = v5.ToDecimal ( ); decimal a6 = v6.ToDecimal ( ); decimal a7 = v7.ToDecimal ( ); Assert.AreEqual ( ( decimal ) 123.4, a1 ); Assert.AreEqual ( ( decimal ) 123.4, a2 ); Assert.AreEqual ( ( decimal ) 1234.5, a3 ); Assert.AreEqual ( ( decimal ) 1234.5, a4 ); Assert.AreEqual ( ( decimal ) 123, a5 ); Assert.AreEqual ( ( decimal ) 1234567.89, a6 ); Assert.AreEqual ( ( decimal ) 1234567.89, a7 ); } /// <summary> /// /// </summary> [TestMethod] public void Swap_Char_Test ( ) { string v6 = "1,234,567.89"; string v7 = "1.234.567,89"; string a1 = v6.SwapChar ( ',', '.' ); string a2 = v7.SwapChar ( ',', '.' ); Assert.AreEqual ( "1.234.567,89", a1 ); Assert.AreEqual ( "1,234,567.89", a2 ); }}
/// <summary>
///
/// </summary>
public static class NumberExtensions
{
/// Convert string value to decimal ignore the culture.
/// <param name="value">The value.</param>
/// <returns>Decimal value.</returns>
public static decimal ToDecimal ( this string value )
decimal number;
string tempValue = value;
var punctuation = value.Where ( x => char.IsPunctuation ( x ) ).Distinct ( );
int count = punctuation.Count ( );
NumberFormatInfo format = CultureInfo.InvariantCulture.NumberFormat;
switch ( count )
case 0:
break;
case 1:
tempValue = value.Replace ( ",", "." );
case 2:
if ( punctuation.ElementAt ( 0 ) == '.' )
tempValue = value.SwapChar ( '.', ',' );
default:
throw new InvalidCastException ( );
}
number = decimal.Parse ( tempValue, format );
return number;
/// Swaps the char.
/// <param name="from">From.</param>
/// <param name="to">To.</param>
/// <returns></returns>
public static string SwapChar ( this string value, char from, char to )
if ( value == null )
throw new ArgumentNullException ( "value" );
StringBuilder builder = new StringBuilder ( );
foreach ( var item in value )
char c = item;
if ( c == from )
c = to;
else if ( c == to )
c = from;
builder.Append ( c );
return builder.ToString ( );
[TestClass]
public class NumberTest
[TestMethod]
public void Convert_To_Decimal_Test ( )
string v1 = "123.4";
string v2 = "123,4";
string v3 = "1,234.5";
string v4 = "1.234,5";
string v5 = "123";
string v6 = "1,234,567.89";
string v7 = "1.234.567,89";
decimal a1 = v1.ToDecimal ( );
decimal a2 = v2.ToDecimal ( );
decimal a3 = v3.ToDecimal ( );
decimal a4 = v4.ToDecimal ( );
decimal a5 = v5.ToDecimal ( );
decimal a6 = v6.ToDecimal ( );
decimal a7 = v7.ToDecimal ( );
Assert.AreEqual ( ( decimal ) 123.4, a1 );
Assert.AreEqual ( ( decimal ) 123.4, a2 );
Assert.AreEqual ( ( decimal ) 1234.5, a3 );
Assert.AreEqual ( ( decimal ) 1234.5, a4 );
Assert.AreEqual ( ( decimal ) 123, a5 );
Assert.AreEqual ( ( decimal ) 1234567.89, a6 );
Assert.AreEqual ( ( decimal ) 1234567.89, a7 );
public void Swap_Char_Test ( )
string a1 = v6.SwapChar ( ',', '.' );
string a2 = v7.SwapChar ( ',', '.' );
Assert.AreEqual ( "1.234.567,89", a1 );
Assert.AreEqual ( "1,234,567.89", a2 );
eiee3dmh6#
很好,但它仍然不是100%正确。当你使用情况1:你自动假设,','代表十进制数字。你至少应该检查它是否出现不止一次,因为在这种情况下,它是一个组分隔符号
case 1: var firstPunctuation = linq.ElementAt(0); var firstPunctuationOccurence = value.Where(x => x == firstPunctuation).Count(); if (firstPunctuationOccurence == 1) { // we assume it's a decimal separator (and not a group separator) value = value.Replace(firstPunctuation.ToString(), format.NumberDecimalSeparator); } else { // multiple occurence means that symbol is a group separator value = value.Replace(firstPunctuation.ToString(), format.NumberGroupSeparator); } break;
var firstPunctuation = linq.ElementAt(0);
var firstPunctuationOccurence = value.Where(x => x == firstPunctuation).Count();
if (firstPunctuationOccurence == 1)
// we assume it's a decimal separator (and not a group separator)
value = value.Replace(firstPunctuation.ToString(), format.NumberDecimalSeparator);
else
// multiple occurence means that symbol is a group separator
value = value.Replace(firstPunctuation.ToString(), format.NumberGroupSeparator);
t8e9dugd7#
使用TryParse两次,两种样式代表两种可能性如果只有一个返回值,则使用该值如果两者都返回值,则使用绝对值较小的值。如果你使用了错误的样式,TryParse将为使用分组和小数分隔符的数字返回0,但是如果你的字符串中没有分组分隔符(例如,一个数字小于1000),它将在两种情况下返回值,但是“错误”的数字将更大(绝对值)
4dc9hkyq8#
更简单的方法来获得十进制值作为字符串从字符串值与逗号或点作为小数点分隔符或逗号作为千位分隔符
public static string StringToDecimalString(string str) { if (str.TrimEnd(new char[0]).Length == 0) { return "0"; } decimal num = 0; try { num = Convert.ToDecimal(str.Replace(".", ",").Replace(" ", "")); } catch { try { num = Convert.ToDecimal(str.Replace(",", ".")); } catch { return "0"; } } return num.ToString(); }
public static string StringToDecimalString(string str)
if (str.TrimEnd(new char[0]).Length == 0)
return "0";
decimal num = 0;
try
num = Convert.ToDecimal(str.Replace(".", ",").Replace(" ", ""));
catch
num = Convert.ToDecimal(str.Replace(",", "."));
return num.ToString();
8条答案
按热度按时间mwg9r5ms1#
您可以创建一个临时
CultureInfo
对象,以便在解析时使用。字符串
cgfeq70w2#
我找到了另一种方法。看起来很奇怪,但对我来说很有效。
因此,如果您不了解目标系统的文化,也不知道将获得哪个值,例如12.33或12,33,您可以执行以下操作
字符串
gg0vcinb3#
您只需要在调用
Parse
时设置正确的区域性,如下所示:字符串
50pmv0ei4#
您有以下可能性:
1.你知道文化
1.使用计算机已安装的当前区域性设置
1.让用户决定在程序中设置其区域性->用户设置
1.你不了解文化
1.你必须做出决定:你必须定义并记录你的决定
1.猜测:你试着解析,试着解析,试着……直到你得到有效的数字
ufj5ltwl5#
下面是我的实现,有什么好主意吗?
字符串
eiee3dmh6#
很好,但它仍然不是100%正确。当你使用情况1:你自动假设,','代表十进制数字。你至少应该检查它是否出现不止一次,因为在这种情况下,它是一个组分隔符号
字符串
t8e9dugd7#
使用TryParse两次,两种样式代表两种可能性
如果只有一个返回值,则使用该值如果两者都返回值,则使用绝对值较小的值。
如果你使用了错误的样式,TryParse将为使用分组和小数分隔符的数字返回0,但是如果你的字符串中没有分组分隔符(例如,一个数字小于1000),它将在两种情况下返回值,但是“错误”的数字将更大(绝对值)
4dc9hkyq8#
更简单的方法来获得十进制值作为字符串从字符串值与逗号或点作为小数点分隔符或逗号作为千位分隔符
字符串