.net 最好的方法转换字符串到小数分隔符“.”和“,”不敏感的方式?

332nm8kg  于 2023-11-20  发布在  .NET
关注(0)|答案(8)|浏览(225)

应用程序处理表示来自不同区域性的小数的字符串。例如,“1.1”和“1,1”是相同的值。
我玩了Decimal.TryParse标志组合,但不能达到我想要的结果。“1,1”变成了“11”或“0”毕竟。
有没有可能在一行代码中将这样的字符串转换为十进制,而不预先将“,”char替换为“.”或使用NumberFormat.NumberDecimalSeparator
你怎么处理这种情况?
在此先谢谢您!

mwg9r5ms

mwg9r5ms1#

您可以创建一个临时CultureInfo对象,以便在解析时使用。

  1. // get a temporary culture (clone) to modify
  2. var ci = CultureInfo.InvariantCulture.Clone() as CultureInfo;
  3. ci.NumberFormat.NumberDecimalSeparator = ",";
  4. decimal number = decimal.Parse("1,1", ci); // 1.1

字符串

cgfeq70w

cgfeq70w2#

我找到了另一种方法。看起来很奇怪,但对我来说很有效。
因此,如果您不了解目标系统的文化,也不知道将获得哪个值,例如12.33或12,33,您可以执行以下操作

  1. string amount = "12.33";
  2. // or i.e. string amount = "12,33";
  3. var c = System.Threading.Thread.CurrentThread.CurrentCulture;
  4. var s = c.NumberFormat.CurrencyDecimalSeparator;
  5. amount = amount.Replace(",", s);
  6. amount = amount.Replace(".", s);
  7. decimal transactionAmount = Convert.ToDecimal(amount);

字符串

gg0vcinb

gg0vcinb3#

您只需要在调用Parse时设置正确的区域性,如下所示:

  1. string s = "11,20";
  2. decimal c1 = decimal.Parse(s, new CultureInfo("fr-FR"));
  3. decimal c2 = decimal.Parse(s, new CultureInfo("en-AU"));
  4. Console.WriteLine(c1);
  5. Console.WriteLine(c2);

字符串

50pmv0ei

50pmv0ei4#

您有以下可能性:
1.你知道文化
1.使用计算机已安装的当前区域性设置
1.让用户决定在程序中设置其区域性->用户设置
1.你不了解文化
1.你必须做出决定:你必须定义并记录你的决定
1.猜测:你试着解析,试着解析,试着……直到你得到有效的数字

ufj5ltwl

ufj5ltwl5#

下面是我的实现,有什么好主意吗?

  1. /// <summary>
  2. ///
  3. /// </summary>
  4. public static class NumberExtensions
  5. {
  6. /// <summary>
  7. /// Convert string value to decimal ignore the culture.
  8. /// </summary>
  9. /// <param name="value">The value.</param>
  10. /// <returns>Decimal value.</returns>
  11. public static decimal ToDecimal ( this string value )
  12. {
  13. decimal number;
  14. string tempValue = value;
  15. var punctuation = value.Where ( x => char.IsPunctuation ( x ) ).Distinct ( );
  16. int count = punctuation.Count ( );
  17. NumberFormatInfo format = CultureInfo.InvariantCulture.NumberFormat;
  18. switch ( count )
  19. {
  20. case 0:
  21. break;
  22. case 1:
  23. tempValue = value.Replace ( ",", "." );
  24. break;
  25. case 2:
  26. if ( punctuation.ElementAt ( 0 ) == '.' )
  27. tempValue = value.SwapChar ( '.', ',' );
  28. break;
  29. default:
  30. throw new InvalidCastException ( );
  31. }
  32. number = decimal.Parse ( tempValue, format );
  33. return number;
  34. }
  35. /// <summary>
  36. /// Swaps the char.
  37. /// </summary>
  38. /// <param name="value">The value.</param>
  39. /// <param name="from">From.</param>
  40. /// <param name="to">To.</param>
  41. /// <returns></returns>
  42. public static string SwapChar ( this string value, char from, char to )
  43. {
  44. if ( value == null )
  45. throw new ArgumentNullException ( "value" );
  46. StringBuilder builder = new StringBuilder ( );
  47. foreach ( var item in value )
  48. {
  49. char c = item;
  50. if ( c == from )
  51. c = to;
  52. else if ( c == to )
  53. c = from;
  54. builder.Append ( c );
  55. }
  56. return builder.ToString ( );
  57. }
  58. }
  59. [TestClass]
  60. public class NumberTest
  61. {
  62. /// <summary>
  63. ///
  64. /// </summary>
  65. [TestMethod]
  66. public void Convert_To_Decimal_Test ( )
  67. {
  68. string v1 = "123.4";
  69. string v2 = "123,4";
  70. string v3 = "1,234.5";
  71. string v4 = "1.234,5";
  72. string v5 = "123";
  73. string v6 = "1,234,567.89";
  74. string v7 = "1.234.567,89";
  75. decimal a1 = v1.ToDecimal ( );
  76. decimal a2 = v2.ToDecimal ( );
  77. decimal a3 = v3.ToDecimal ( );
  78. decimal a4 = v4.ToDecimal ( );
  79. decimal a5 = v5.ToDecimal ( );
  80. decimal a6 = v6.ToDecimal ( );
  81. decimal a7 = v7.ToDecimal ( );
  82. Assert.AreEqual ( ( decimal ) 123.4, a1 );
  83. Assert.AreEqual ( ( decimal ) 123.4, a2 );
  84. Assert.AreEqual ( ( decimal ) 1234.5, a3 );
  85. Assert.AreEqual ( ( decimal ) 1234.5, a4 );
  86. Assert.AreEqual ( ( decimal ) 123, a5 );
  87. Assert.AreEqual ( ( decimal ) 1234567.89, a6 );
  88. Assert.AreEqual ( ( decimal ) 1234567.89, a7 );
  89. }
  90. /// <summary>
  91. ///
  92. /// </summary>
  93. [TestMethod]
  94. public void Swap_Char_Test ( )
  95. {
  96. string v6 = "1,234,567.89";
  97. string v7 = "1.234.567,89";
  98. string a1 = v6.SwapChar ( ',', '.' );
  99. string a2 = v7.SwapChar ( ',', '.' );
  100. Assert.AreEqual ( "1.234.567,89", a1 );
  101. Assert.AreEqual ( "1,234,567.89", a2 );
  102. }
  103. }

字符串

展开查看全部
eiee3dmh

eiee3dmh6#

很好,但它仍然不是100%正确。当你使用情况1:你自动假设,','代表十进制数字。你至少应该检查它是否出现不止一次,因为在这种情况下,它是一个组分隔符号

  1. case 1:
  2. var firstPunctuation = linq.ElementAt(0);
  3. var firstPunctuationOccurence = value.Where(x => x == firstPunctuation).Count();
  4. if (firstPunctuationOccurence == 1)
  5. {
  6. // we assume it's a decimal separator (and not a group separator)
  7. value = value.Replace(firstPunctuation.ToString(), format.NumberDecimalSeparator);
  8. }
  9. else
  10. {
  11. // multiple occurence means that symbol is a group separator
  12. value = value.Replace(firstPunctuation.ToString(), format.NumberGroupSeparator);
  13. }
  14. break;

字符串

展开查看全部
t8e9dugd

t8e9dugd7#

使用TryParse两次,两种样式代表两种可能性
如果只有一个返回值,则使用该值如果两者都返回值,则使用绝对值较小的值。
如果你使用了错误的样式,TryParse将为使用分组和小数分隔符的数字返回0,但是如果你的字符串中没有分组分隔符(例如,一个数字小于1000),它将在两种情况下返回值,但是“错误”的数字将更大(绝对值)

4dc9hkyq

4dc9hkyq8#

更简单的方法来获得十进制值作为字符串从字符串值与逗号或点作为小数点分隔符或逗号作为千位分隔符

  1. public static string StringToDecimalString(string str)
  2. {
  3. if (str.TrimEnd(new char[0]).Length == 0)
  4. {
  5. return "0";
  6. }
  7. decimal num = 0;
  8. try
  9. {
  10. num = Convert.ToDecimal(str.Replace(".", ",").Replace(" ", ""));
  11. }
  12. catch
  13. {
  14. try
  15. {
  16. num = Convert.ToDecimal(str.Replace(",", "."));
  17. }
  18. catch
  19. {
  20. return "0";
  21. }
  22. }
  23. return num.ToString();
  24. }

字符串

展开查看全部

相关问题