22

问题:假设您使用的是点“。” 作为区域设置中的小数分隔符,并使用逗号对字符串进行编码。

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);

并以某种方式替换 from ",",sepdec,这样如果它是逗号,它将保持逗号,如果用户使用点,则替换为实际的点。

提示?

编辑:最近,许多用户发布了有用的信息,如果您的分隔符设置为“,”,则使用NumberStyles.Any, CultureInfo.GetCultureInfo("pt-PT")a 上的参数tryParse将不起作用,因此它几乎不能满足使 tryparse“通用”的前提。

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

4

6 回答 6

13

我知道该线程有点旧,但我尝试提供一个答案。

我使用正则表达式来确定字符串中使用的数字格式。正则表达式还匹配没有小数分隔符的数字(“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);

高温高压

托马斯

于 2016-10-21T10:46:13.503 回答
0

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

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

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

于 2021-01-27T18:55:16.190 回答
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;
}
于 2021-07-29T10:39:03.507 回答
0

我只想说 HTH Thomas 解决方案在我的项目中运行良好,除了尝试用逗号解析负十进制数时。对此的一种解决方案可能未优化,因为我不完全理解正则表达式 Ismatch 代码,但可行的是在 ifs 语句中的数字之前添加“-”的可能性,如下所示:

        var cultureInfo = CultureInfo.InvariantCulture;
        if (Regex.IsMatch(equation.inputFieldsTexts[i], @"^(:?[\d,]+\.)*\d+$") || Regex.IsMatch(equation.inputFieldsTexts[i], @"^(:?[-\d,]+\.)*\d+$"))
        {
            cultureInfo = new CultureInfo("en-US");
        }
        // if the second regex matches, the number string is in DE culture
        if (Regex.IsMatch(equation.inputFieldsTexts[i], @"^(:?[\d.]+,)*\d+$") || Regex.IsMatch(equation.inputFieldsTexts[i], @"^(:?[-\d.]+,)*\d+$"))
        {
            cultureInfo = new CultureInfo("de-DE");
        }
于 2022-01-14T11:43:48.003 回答
-1

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

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

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

在 , 中tryParse,为了使其具有通用性,我们将读取字符串中的点和逗号,并将它们转换为我们定义为的小数分隔符sepdec

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

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

于 2015-04-05T01:10:14.267 回答
-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
        }
于 2021-02-21T18:43:06.073 回答