System.Decimal轮次分配

Wis*_*yEh 1 .net clr decimal rounding

任何人都可以解释为什么我得到以下结果?

Dim badDecimal As Decimal = 54.50327999999999 
Dim expectedDecimal As Decimal = CDec("54.50327999999999")
Run Code Online (Sandbox Code Playgroud)

badDecimal = 54.50328D,而expectedDecimal = 54.50327999999999D.我的理解是badDecimal应该包含expectedDecimal的值(expectedDecimal可以保存正确值的事实表明Decimal类型具有保存值的精度).

提前感谢任何帮助.

ang*_*son 6

根据此页面:十进制数据类型(Visual Basic),您需要使用大写字符后缀十进制文字值D,否则编译器将尝试将其编译为适当但不同的数字类型,如Integer,Long,Double,取决于使用的常数值.

在您的情况下,代码基本上看起来像编译器:

Dim badDecimal As Decimal = (constant of type System.Double)
Run Code Online (Sandbox Code Playgroud)

因此,在编译时,常量值失去了精度.

只需将代码更改为:

Dim badDecimal As Decimal = 54.50327999999999D
                                             ^
                                             +-- add this
Run Code Online (Sandbox Code Playgroud)

它应该按预期工作.

但是,我厌倦了期望两个变量进行比较相同,StackOverflow上有关于浮点类型"问题"的问题至少让我告诉你,你可能在第N个十进制中有一个小的差异,小到足以没有使它到显示器或调试器,但足以使两个变量比较不同.

因此,如果你打算比较它们,请记住这一点,典型的方法是从另一个值中减去一个值,取其绝对值,并将其与一些微小的值进行比较,说"我接受一个不同的大,但不是更大" .

即.像这样:

If Math.Abs(badDecimal - expectedDecimal) < 0.000001 Then
Run Code Online (Sandbox Code Playgroud)

而不是这个:

If badDecimal = expectedDecimal Then
Run Code Online (Sandbox Code Playgroud)