最佳解析浮点数的方法是什么?

50

什么是在C#中解析float的最佳方法? 我知道TryParse,但我特别想知道点、逗号等。

我的网站出现了问题。在我的开发服务器上,逗号表示小数,点表示分隔符。然而,在生产服务器上,情况正好相反。 如何最好地解决这个问题?


1
愿意这样做,因为似乎每个人都在这样做。 我个人尽量避免使用<3个字符的搜索词。我认为这是从过去所有搜索都必须>3个字符的时代留下来的习惯。此外,#号让我的蜘蛛感到不适。 - Boris Callens
11个回答

65

我同意leppie的回答;为了用代码表示出来:

string s = "123,456.789";
float f = float.Parse(s, CultureInfo.InvariantCulture);

28

根据输入来源而定。

如果输入来自用户,您应该使用用户/页面正在使用的CultureInfo (Thread.CurrentThread.CurrentUICulture)。

您可以通过查看HttpRequest.UserLanguages属性来获取用户的文化信息。(不完全正确,但我发现这是一个非常好的第一猜测)。有了这些信息,您可以在页面开始时设置Thread.CurrentThread.CurrentUICulture

如果输入来自内部源,则可以使用InvariantCulture来解析字符串。

如果您的输入来自受控源,则使用Parse方法更容易。也就是说,您已经验证了字符串。如果失败,Parse会抛出一个(较慢的)异常。

如果输入不受控制(来自用户或其他Internet源),那么对我来说TryParse看起来更好。


7

如果你想为内部目的保留值(数字、日期、时间等),每次使用"InvariantCulture"进行格式化和解析值。"InvariantCulture"在任何计算机、任何操作系统上都是相同的,无论用户的文化、语言等如何...

string strFloat = (15.789f).ToString(System.Globalization.CultureInfo.InvariantInfo);
float numFloat  = float.Parse(System.Globalization.CultureInfo.InvariantInfo, strFloat);
string strNow   = DateTime.Now.ToString(System.Globalization.CultureInfo.InvariantInfo);
DateTime now    = DateTime.Parse(System.Globalization.CultureInfo.InvariantInfo, strNow);

true,但与问题无关。 - Boris Callens

6

您可以使用解析的重载版本,其中包含要使用的文化设置?

例如:

double number = Double.Parse("42,22", new CultureInfo("nl-NL").NumberFormat); // dutch number formatting

如果您控制所有数据,则应在代码中使用“CultureInfo.InvariantCulture”。


4

在使用 Try/Parse 进行解析时,请使用中性文化(或您了解的文化)。


1

传入一个CultureInfoNumberFormatInfo,表示您要解析浮点数的文化,这控制小数、组分隔符等使用的字符。

例如,为了确保'.'字符被视为小数指示器,您可以传入CultureInfo.InvariantCulture(在服务器应用程序中通常非常有用,在那里您倾向于希望无论环境文化如何都保持一致)。


0
一种方法是强制本地化使用点而不是逗号作为分隔符 - 这样你的代码将在所有 Windows 机器上独立于所选语言和设置以相同的方式工作。
这种方法适用于小型应用程序,如测试应用程序,控制台应用程序等。对于已使用本地化的应用程序来说,这并不是很有用,但取决于应用程序的要求。
var CurrentCultureInfo = new CultureInfo("en", false);
CurrentCultureInfo.NumberFormat.NumberDecimalSeparator = ".";
CurrentCultureInfo.NumberFormat.CurrencyDecimalSeparator = ".";
Thread.CurrentThread.CurrentUICulture = CurrentCultureInfo;
Thread.CurrentThread.CurrentCulture = CurrentCultureInfo;
CultureInfo.DefaultThreadCurrentCulture = CurrentCultureInfo;

这段代码强制使用点号('.')而不是逗号,需要放置在应用程序启动时。


0

尽量避免使用float.Parse,而是使用TryParse,因为它的性能更好,但执行相同的工作。 这也适用于double、DateTime等类型...

(有些类型还提供TryParseExact,它的性能甚至更好!)


1
TryParse 真的比所有数据都有效时更快吗?我预计在“成功”案例中它们的表现相同,但由于抛出异常的代价,对于失败而言 TryParse 会比 Parse 更快。 - Jon Skeet
再说了,如果 TryParse 返回 false,你会抛出异常吗?在这种情况下,float.Parse 比 TryParse 更有效率! - Sklivvz
如果您解析的字符串大多都是有效的浮点数,则tryparse肯定更快。如果有很多不同的字符串,也许parse才是更好的选择,但当获取成千上万个在字符串表示中全部(在99%的情况下)都是有效浮点数的字符串时,请使用tryparse。 - Joachim Kerschbaumer
1
你确定你不是想说反了吗?我猜测只有在有大量正确的浮点数时,Parse 才有用,而 TryParse 有一些开销,只有当字符串无效的可能性较大时才会产生回报。 - Boris Callens

0

源是从网站输入的。我不能依赖它的有效性。所以我选择了之前提到的TryParse。 但我无法弄清如何将当前区域设置传递给它。

此外,这会给我当前运行服务器的区域设置,但由于这是全球网络,用户可以来自任何地方...


0

你可以通过一个简单的语句了解你的服务器当前的文化(Culture):

System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;

请注意,有一个CurrentUICulture属性,但在多语言应用程序中,UICulture是从ResourceMeanager使用的。对于数字格式化,您必须考虑CurrentCulture。
希望这可以帮助您。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接