事实上,我有多个系统可以生成数字数据,并且它们存储在文本文件中的某个Web服务器上。一些系统使用小数点作为分数分隔符,一些系统使用十进制逗号作为相同。
应用程序(胖客户端,.net 2.0)也可以在任何一种系统上运行。
所以在经历了一些磕磕绊绊之后我做到了:(http://pastebin.com/vhLXABDD)
public static bool HasDecimalComma;
public static bool HasDecimalPeriod;
public static double GetNumber(string NumberString)
{
if (!HasDecimalComma && !HasDecimalPeriod)
{
string s = string.Format("{0:0.0}", 123.123);
if (s.Contains('.'))
{
HasDecimalPeriod = true;
}
else if (s.Contains(','))
{
HasDecimalComma = true;
}
else
{
throw new SystemException(string.Format("strange number format '{0}'", s));
}
}
if (HasDecimalComma)
{
return double.Parse(NumberString.Replace('.', ','));
}
if (HasDecimalPeriod)
{
return double.Parse(NumberString.Replace(',', '.'));
}
throw new ArgumentException(string.Format("can't parse '{0}'", NumberString));
}
你会建议更好,更优雅的方式吗?
编辑:
我很抱歉之前没有提及它,因为你的答案倾向于那个方向 - 我不能用数字存储生成文化,我只能尝试'检测'它。
答案 0 :(得分:2)
试试这个:
static double GetDouble(string s)
{
double d;
var formatinfo = new NumberFormatInfo();
formatinfo.NumberDecimalSeparator = ".";
if (double.TryParse(s, NumberStyles.Float, formatinfo, out d))
{
return d;
}
formatinfo.NumberDecimalSeparator = ",";
if (double.TryParse(s, NumberStyles.Float, formatinfo, out d))
{
return d;
}
throw new SystemException(string.Format("strange number format '{0}'", s));
}
答案 1 :(得分:0)
如果您无法更改呼叫站点,并且您保证小数点分隔符旁边不存在其他类型的分隔符,则您可以或多或少地使用您的方法。我建议
HasDecimalComma
和HasDecimalPeriod
移动到方法的主体 - 在这种情况下绝对不需要全局状态。TryParse
代替Parse
,因为预计这些数字可能有问题。InvariantCulture
文化(它有一个小数句点)。这些内容如下:
///comment the method assumptions here
///otherwise the method might seem wrong
public static double GetNumber(string numberString)
{
bool hasDecimalComma = numberString.Contains(',');
if (hasDecimalComma)
numberString = numberString.Replace(',', '.')
double result;
bool success = double.TryParse(numberString,
NumberStyles.Float,
CultureInfo.InvariantCulture,
out result);
if (success)
return result;
else
throw new ArgumentException(
string.Format("can't parse '{0}'", numberString));
}
(老答案,原则上是好的,在实践中是不可能的)
我建议沿着字符串存储生成文化,然后使用它来调用方法,沿着这些行(使用double.TryParse
):
public static double GetNumber(string numberString, CultureInfo culture)
{
double result;
bool success = double.TryParse(numberString,
NumberStyles.Float | NumberStyles.AllowThousands,
culture,
out result);
if (success)
return result;
else
throw new ArgumentException(
string.Format("can't parse '{0}'", numberString));
}
答案 2 :(得分:0)
只需使用当前文化和正确的数字格式标记即可。当然,您必须针对可能存储在数据库中的所有文化进行测试。更好:在将数字存储到数据库之前,将数字转换为CultureInfo.Invariant文化。或者:存储号码时也存储文化标识符。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
const string toTest = "1.006,30";
float number;
if (float.TryParse(toTest, NumberStyles.AllowDecimalPoint | NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.CurrentCulture, out number))
Console.WriteLine("Success: {0}", number);
else
Console.WriteLine("Failure: strange number format");
Console.WriteLine("Press any key to finish");
Console.ReadKey();
}
}
}
答案 3 :(得分:0)
除非您的某些客户使用波斯语(fa
,fa-IR
代码)作为他们的文化,否则我认为您很高兴:
// apparently, Persians use '/' as the decimal separator
var slash = CultureInfo
.GetCultures(CultureTypes.AllCultures)
.Where(c =>
c.NumberFormat.NumberDecimalSeparator != "," &&
c.NumberFormat.NumberDecimalSeparator != ".")
.ToList();