为啥 Convert.ToDecimal(3.1922) 显示为 31922?

Posted

技术标签:

【中文标题】为啥 Convert.ToDecimal(3.1922) 显示为 31922?【英文标题】:Why is Convert.ToDecimal(3.1922) showing as 31922?为什么 Convert.ToDecimal(3.1922) 显示为 31922? 【发布时间】:2012-10-28 14:49:02 【问题描述】:

我正在读取一个包含值的 XML 文件。当我读到它们时,它们是字符串。

因此,当我尝试将它们转换为 DoubleDecimal 时,这一点就消失了。

decimal dec = Convert.ToDecimal("3.1922");             
MessageBox.Show(dec.ToString()); // 31922

我做错了什么?

【问题讨论】:

【参考方案1】:

这和你现在的文化有关

decimal dec = Convert.ToDecimal("3.1922",CultureInfo.CreateSpecificCulture("de-DE"));
MessageBox.Show(dec.ToString()); //31922

dec = Convert.ToDecimal("3.1922", CultureInfo.CreateSpecificCulture("en-US"));
MessageBox.Show(dec.ToString()); //3.1922

dec = Convert.ToDecimal("3,1922", CultureInfo.CreateSpecificCulture("de-DE"));
MessageBox.Show(dec.ToString()); //3.1922

【讨论】:

您也应该添加推荐的解决方案,即明确指定CultureInfo.InvariantCulture 那么最好的方法是什么?使用 CultureInfo.InvariantCulture 或创建一个“有效”的文化。 IE。 CreateSpecificCulture("en-US") 像我想要的那样工作。 @Niels 这取决于你的具体情况,但如果你想让你的代码适用于许多语言环境,请使用CultureInfo.InvariantCulture @L.B.感谢您的回答。 XML 中的值将始终采用这种格式,并且我的应用程序的 GUI 将始终使用英文。那么,最好的解决方案是什么? @Niels 我会使用InvariantCulture【参考方案2】:

在您当前的文化中,. 用作千位分隔符。你可以这样验证:

var culture = Thread.CurrentThread.CurrentCulture;
var numberFormat = culture.NumberFormat;
string groupSeparator = numberFormat.NumberGroupSeparator; // will be .
string decimalSeparator = numberFormat.NumberDecimalSeparator; // will be ,

您可以指定所需的解析文化:

decimal dec = Decimal.Parse("3.1922", new CultureInfo("en-US"));

或者您可以将您的文化设置为当前:

Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
decimal dec = Decimal.Parse("3.1922");

【讨论】:

@Ons 你怎么知道尼尔斯的文化?例如,德国文化使用. 作为千位分隔符。 我说的是一般的美国文化。此处未指定文化。当我运行代码时。它显示正常。 这里没有指定文化那么,你为什么确定当前的OP环境文化? @Ons 如果没有指定文化,则使用本地文化。你不能假设这种文化就是美国文化。必须明确使用必须InvariantCulture 才能使此代码可靠地工作。 这实际上是正确的。所以在这种情况下,我们可以使用文化不变量,它会正常工作吗?【参考方案3】:

检查您的 NumberFormat.NumberDecimalSeparator。

【讨论】:

【参考方案4】:

首先在public form1()after InitializeComponent();中添加这些代码:

public Form1()
    
        InitializeComponent();
        System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
        System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
    

然后在任何你想要的地方使用你的代码:

decimal dec = Convert.ToDecimal("3.1922");
        MessageBox.Show(dec.ToString());

更新:

如果您不希望全局更改,则应在显示小数之前添加代码。

private void ShowDecimal_Click(object sender, EventArgs e)
    
        System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
        System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
        decimal dec = Convert.ToDecimal("3.1922");
        MessageBox.Show(dec.ToString());
    

更新 2:

decimal dec = Decimal.Parse("3.1922", new CultureInfo("en-US"));
MessageBox.Show(dec.ToString());

【讨论】:

局部问题的全局更改 => 糟糕的设计 @CodesInChaos 他可以在他的代码之前更改它。我只是给他指路;) 这让事情变得更糟。由于现在单击按钮会全局更改状态而不恢复它。

以上是关于为啥 Convert.ToDecimal(3.1922) 显示为 31922?的主要内容,如果未能解决你的问题,请参考以下文章

Decimal.Parse() 与 Convert.ToDecimal() [重复]

Convert.ToDecimal 为简单字符串引发异常

为啥要Convert.toDouble,直接赋值不可以?

使用 Convert.ToDecimal() 会导致 C# 中的值四舍五入。如何克服这个问题?

VB.Net Convert ToDecimal 不适用于逗号

decimal.TryParse和Convert.ToDecimal+try{} catch{}的性能比较