将带逗号的字符串转换为double和int是不同的。为什么?

时间:2014-04-23 11:28:23

标签: c# string int double

我正在从旧的MFC GUI迁移到C#。

当我遇到将字符串转换为整数类型的意外异常时,我正在构建基于表单的GUI。我认为它的工作原理与将字符串转换为double相同。

string str = "1,000";
double dthou = Convert.ToDouble(str);   // OK
int ithou = Convert.ToInt32(str);       // raises an exception

转换为double会给出正确的值:1000.0。 对于int转换,我能够得到一个解决方案:Convert.ToInt32() a string with Commas

但我很好奇这背后是否有任何理由。 或者,我错过了什么?

我能够找到类似但不完全重复的问题: Number parsing weirdness

[编辑]了解了文化问题。

我处于一种文化冲击中,因为到目前为止,在韩国,浮点数和整数都用“,”表示,对于数千组和“。”。对于小数点(至少在现实世界中,在韩国,我的意思是,我认为......)。 我想我将不得不接受MS Visual Studio的当前设置并继续。

睡过这个问题之后

[EDIT2]。

我认为这更多是对格式化字符串的不一致处理。 ToDouble接受带有千位分隔符的字符串(在我的文化中,逗号),但ToInt32没有。如果ToDoublefloat | allowThousands,那么为什么ToInt32 integer | allowThousands不是{{1}}就是我要问的。

3 个答案:

答案 0 :(得分:3)

对于双重转换,有两种可能性:

  1. 在您的文化中,,是数字组分隔符。因此转换成功并返回值1000
  2. 或者,在您的文化中,,用作小数点分隔符。再次转换为浮点成功,但这次返回1
  3. 要转换为整数,"1,000"根本不是整数。鉴于您的命名,我怀疑,是一个数字组分隔符。并期望ToInt32()以这种方式对待它。但是ToInt32()不接受数字组分隔符。 ToInt32()的有效字符为09-+的可选符号前缀以及前导或尾随空格。

答案 1 :(得分:2)

在你的个人资料中,它说你来自韩国。这就是为什么我认为你现在的文化是ko-KR。 (还有你said。)

它是NumberDecimalSeparator .但是NumberGroupSeparator,

enter image description here

您的Convert.ToDouble有效并假设您的,是千位分隔符,而不是十进制分隔符。这就是为什么您的dthou1000而不是1

Convert.ToInt32(string)明确使用Int32.Parse(string, CultureInfo.CurrentCulture),此方法implemented喜欢;

public static int Parse(String s, IFormatProvider provider)
{
    return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
}

正如您所看到的,此方法使用NumberStyles.Integer作为默认值。这就是为什么你的字符串只能成功地解析它们中的一个;

  • 领先的空白区域
  • 尾随空格
  • 领先标志(正面或负面)

由于你的字符串有数千个分隔符或十进制分隔符(这取决于你用过的字符串),这个方法会引发异常。

除此之外,您可以使用Int32.Parse(String, NumberStyles, IFormatProvider) overload来指定NumberStyles NumberStyles.AllowDecimalPointNumberStyles.AllowThousands

作为一个例子;

string str = "1,000";
int ithou = Int32.Parse(str, NumberStyles.AllowThousands,
                        new CultureInfo("ko-KR"));
Console.WriteLine(ithou); // Prints 1000

如果您希望获得1,可以使用CultureInfo.Clone method到您的文化中并设置NumberDecimalSeparatorNumberGroupSeparator属性,例如;

string str = "1,000";
CultureInfo c = (CultureInfo)CultureInfo.GetCultureInfo("ko-KR").Clone();
c.NumberFormat.NumberDecimalSeparator = ",";
c.NumberFormat.NumberGroupSeparator = ".";
int dthou = Int32.Parse(str, NumberStyles.AllowDecimalPoint, c);
Console.WriteLine(dthou ); // Prints 1
  

我不认为这是一个文化问题。这是不一致的处理   格式化字符串。 ToDouble用逗号接受字符串,但是   ToInt32没有。这就像回到原来的问题,   但是不能实现ToInt32来接受逗号就好了   ToDouble功能?

哦,亲爱的朋友,你还在想错...

在你的情况下,一切都是文化问题。没有这样的事情“ Convert.ToDouble()接受带逗号的字符串,但Convert.ToInt32()”。

让我们再看一下这些方法是如何实现的。

Convert.ToDouble(string)明确使用Double.Parse(value, CultureInfo.CurrentCulture)implemented就像;

public static double Parse(String s, IFormatProvider provider)
{
     return Parse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
}

使用此NumberStyles.Float| NumberStyles.AllowThousands,您可以在代码中同时使用小数点或千位分隔符,但,是您的文化NumberGroupSeparator而不是NumberDecimalSeparator。这就是为什么你的字符串将被解析为数千个seperetor。 没有这样的东西Convert.ToDouble使用带逗号的字符串。它可以使用您当前的文化NumberDecimalSeparatorNumberGroupSeparator取决于您的字符串所具有的字符。如果两者相等,NumberDecimalSeparator将占主导地位并将被使用。

Convert.ToInt32(string)明确使用Int32.Parse(string, CultureInfo.CurrentCulture),而implemented就像;

public static int Parse(String s, IFormatProvider provider)
{
    return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
}

正如我之前所说,NumberStyles.Integer允许你的三个字符串;领先的白色空间,尾随白色空间和领先的正面或负面标志。如果您的字符串包含小数点分隔符或千位分隔符,则无论是逗号还是点,都无法解析。

  

但是无法实现ToInt32以接受逗号   ToDouble功能?

我之前告诉过你。 Convert.ToInt32没有重载需要NumberStyles作为参数。您可以使用Int32.Parse(String, NumberStyles, IFormatProvider) overload指定NumberStyles枚举来解析小数点分隔符或千位分隔符。

答案 2 :(得分:0)

在英国文化中,十进制符号是"。" 。在瑞典文化中,十进制的叹息是",#34;。无数的标志可以是" ",","或"。"。这就是为什么当小数符号与其指定的文化不同时C#抛出异常的原因。