.net Decimal.Parse和Double.Parse行为

.net Decimal.Parse和Double.Parse行为,.net,vb.net,parsing,.net-3.5,.net,Vb.net,Parsing,.net 3.5,我最近偶然发现了一些非直观的行为Decimal.Parse,我想讨论一下。案件如下。 我的程序从另一个程序中以字符串的形式获取数字,“科学”格式化(对我来说是一个黑匣子)。使用Decimal.Parse解析字符串 Dim Value As Decimal = Decimal.Parse(StrValue, Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo) 一切正常,直到它

我最近偶然发现了一些非直观的行为
Decimal.Parse
,我想讨论一下。案件如下。 我的程序从另一个程序中以字符串的形式获取数字,“科学”格式化(对我来说是一个黑匣子)。使用
Decimal.Parse
解析字符串

Dim Value As Decimal = Decimal.Parse(StrValue, Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo)
一切正常,直到它尝试解析
“1.9721522630525295e-31”
。在此字符串上,Decimal.Parse引发OverflowException。“好吧,”我想,“让我们试试双倍!”

这个很好用。种类:结果是
0.0000000000000019721522630525295
。(或:
Double.Parse(StrValue).ToString=“197215226305253E-15”

好的,下次试试

Dim dblValue As Double = Double.Parse(StrValue, Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo)
工作正常,
E-31
保持这种状态

所以,这是我的第一个问题:为什么Double.Parse会这样

编辑通过“这种方式”,我的意思是给我一个比预期大16个数量级的数字(
E-15
而不是
E-31
)。问题是由varocarbas回答的:原因是我的本地小数和千位分隔符设置。
“1.9721522630525295e-31”
中的
双解析(StrValue)
处理,类似于千位分隔符(即忽略),因此该值变为
0.00000000000000 19721522630525295

然后,我像以前一样,将结果转换为十进制

Dim decValue = CDec(dblValue)
没有例外,但我得到的值再次是
1.9721522630525295E-15
。 在谷歌上搜索了一段时间后,我了解了
Convert.ToDecimal
,它工作得很好(将
…E-31
转换为
0

第二个问题:我们应该始终使用
Convert.ToDecimal
而从不使用
CDec
还是有一些规则或最佳实践或其他什么

所以,在所有这些之后,我现在使用以下代码

If Not Decimal.TryParse(StrValue, Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo, _
                           Value) Then
    Value = Convert.ToDecimal(Double.Parse(StrValue, Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo))
End If
我的第三个也是最后一个(目前)问题是:这段代码是正确的方法吗


(规格:Visual Studio 2005、.net 3.5,应用程序编译为32位,Windows语言环境设置为德语。)

真的不清楚“为什么Double.Parse会以这种方式运行”是什么意思-您到底希望有什么不同?您是希望它给出不同的值,还是希望调用
ToString
,然后返回原始字符串?这些都是行为的不同方面。还要注意,将
双精度
转换为
十进制
通常是个坏主意-您可能会丢失信息。基本上,
decimal
无法处理接近零的值。你想在这里实现什么?价值意味着什么?(目前我们还不知道应该使用哪种类型。)Double.Parse(StrValue,Globalization.NumberStyles.Float,System.Globalization.NumberFormatInfo.InvariantInfo)强制使用“.”作为十进制分隔符。Parse(StrValue)采用系统中默认的十进制分隔符(似乎是“,”)。这就是为什么Double.Parse(StrValue)错误地理解您的输入。您提出的所有方法在正常情况下都应该表现出等价的行为(尽管请注意,CDec来自.NET之前的旧VB);占这么多小数点位置肯定不好。粗略地说,任何超过Decimal.MaxValue的位数都是一个问题。啊,谢谢@varocabas,我现在明白为什么会有16个数量级的差异了。@JonSkeet我的第一个问题由@varocabas回答:这是因为我系统上的十进制分隔符默认为“,”。内部双变量的预期值为
1.972152630525295E-31
。十进制变量的预期值为
0
If Not Decimal.TryParse(StrValue, Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo, _
                           Value) Then
    Value = Convert.ToDecimal(Double.Parse(StrValue, Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo))
End If