.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