使TryParse与逗号或点小数分隔符兼容

时间:2015-04-04 22:51:21

标签: c# decimal tryparse regional-settings

问题: 我们假设你使用的是一个点"。"作为区域设置中的小数点分隔符,并使用逗号编码了一个字符串。

string str = "2,5";

decimal.TryParse(str, out somevariable);时会发生什么?

somevariable将为0。

你能做些什么来解决它?

1- 你可以

decimal.TryParse(str, NumberStyles.Any, CultureInfo.InvariantCulture, out somevariable);

它将返回25,而不是2.5,这是错误的。

2- 你可以

decimal.TryParse(str.Replace(",","."), out num);

如果用户使用","作为小数分隔符,它将返回正确的值,但是它将不起作用。

我无法解决的可能解决方案:

在区域设置中获取用户小数点分隔符:

char sepdec = Convert.ToChar(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);

并以某种方式替换",",sepdec,这样如果它是逗号就会保留逗号,如果用户使用点,则用实际点替换。

提示?

编辑:如果您的分隔符设置为","最近,许多用户发布了有用的信息,使用NumberStyles.Any, CultureInfo.GetCultureInfo("pt-PT")上的tryParse参数将无效。所以它几乎没有充实填充tryparse" universal"的前提。

我会解决这个问题,如果有人有更多提示,欢迎

6 个答案:

答案 0 :(得分:0)

我找到了一个解决方案,我是这个区域和逗号点主题的初学者,所以如果您有意见以提高对此的理解,请欢迎。

我们首先获取用户在Form{InitializeComponent();}之前的区域选项中设置的小数点分隔符(我想要一个允许我更正代码的通用变量)

 char sepdec = Convert.ToChar(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);

tryParse中,为了让它普遍表现,我们将读取字符串中的点和逗号,并将它们转换为我们定义为sepdec的小数点分隔符

decimal.TryParse(str.Replace(",",sepdec.ToString()).Replace(".",sepdec.ToString()),  out somevariable);

我希望这有帮助,请评论改进建议!

答案 1 :(得分:0)

我知道线程有点老了,但我试着提供答案。

我使用正则表达式来确定字符串中使用的数字格式。 正则表达式也匹配没有小数分隔符的数字(“12345”)。

var numberString = "1,234.56"; // en
// var numberString = "1.234,56"; // de
var cultureInfo = CultureInfo.InvariantCulture;
// if the first regex matches, the number string is in us culture
if (Regex.IsMatch(numberString, @"^(:?[\d,]+\.)*\d+$"))
{
    cultureInfo = new CultureInfo("en-US");
}
// if the second regex matches, the number string is in de culture
else if (Regex.IsMatch(numberString, @"^(:?[\d.]+,)*\d+$"))
{
    cultureInfo = new CultureInfo("de-DE");
}
NumberStyles styles = NumberStyles.Number;
bool isDouble = double.TryParse(numberString, styles, cultureInfo, out number);

HTH

托马斯

答案 2 :(得分:0)

除了检查区域性或替换性之外,还可以使用TryParse并支持两个分隔符而无需太多代码。

double d;
if (double.TryParse("12.3", System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out d))
    Console.WriteLine("Value converted {0}", d);
else
    Console.WriteLine("Unable to parse this number");

答案 3 :(得分:0)

我使用的解决方案是简单地向用户展示解析的值是什么。

我有一个自定义的 TextBox 控件,用于在控件失去焦点等情况时验证输入。如果控件需要一个浮点值(这是一个属性),那么它会尝试解析输入的值。如果 TryParse 成功,我会在控件的文本中显示 out 值。

这样,当用户输入 12.3 时,该值可能会更改为 123,因为在当前文化中 12,3 是预期的。然后由他们决定纠正这个问题。

答案 4 :(得分:0)

这个方法怎么样:

  • 清除字符串中除数字、点、逗号和负号以外的任何内容
  • 取点或逗号的最后一个索引
  • 拆分干净的字符串并从第一部分中删除所有千位分隔符
  • 将两个部分都转换为整数
  • 如有必要,更改第二部分的符号
  • 添加第一部分,第二部分除以小数位
public static bool TryParseDoubleUniversal(this string s, out double result) {
  result = 0.0;
  if (string.IsNullOrEmpty(s)) return false;

  var clean = new string(s.Where(x => char.IsDigit(x) || x == '.' || x == ',' || x == '-').ToArray());
  var iOfSep = clean.LastIndexOfAny(new[] { ',', '.' });
  var partA = clean.Substring(0, iOfSep).Replace(",", string.Empty).Replace(".", string.Empty);
  var partB = clean.Substring(iOfSep + 1);
  if (!int.TryParse(partA, out var intA)) return false;
  if (!int.TryParse(partB, out var intB)) return false;
  if (intA < 0) intB *= -1;
  var dp = double.Parse("1".PadRight(partB.Length + 1, '0'));

  result = intA + intB / dp;
  return true;
}

答案 5 :(得分:-1)

在 Android Xamarin 中,我多次遇到相同的问题。一些解决方案在Android升级到新版本之前一直有效,然后问题再次出现。所以我提出了一个通用的解决方案,效果很好。我将数字输入读取为文本,然后使用自定义解析器将其解析为十进制。

无法解析为十进制时,自定义解析器返回 0。它确实允许包含带逗号或点的十进制数的输入文本,没有组分隔符:

public static decimal ParseTextToDecimal(string decimalText)
        {
            if (decimalText == String.Empty) return 0;
            string temp = decimalText.Replace(',', '.');
            var decText = temp.Split('.');
            if (!Int32.TryParse(decText[0], out int integerPart)) return 0;
            if (decText.Length == 1) return integerPart;
            if (decText.Length == 2)
            {
                if (!Int32.TryParse(decText[1], out int decimalPart)) return 0;

                decimal powerOfTen = 10m;
                for (int i = 1; i < decText[1].Length; i++) powerOfTen *= 10;
                return integerPart + decimalPart / powerOfTen;
            }
            return 0; // there were two or more decimal separators, which is a clear invalid input
        }