2016-11-14 53 views
1

我有一个旧的VBA应用程序,它生成的值如1.123456789123456789123456789E-28。当我使用C#搜索等价数据类型时,我在SO Difference between decimal, float and double in .NET?中发现了这篇文章。根据这篇文章的建议,十进制数据类型在C#中具有最大的大小。所以我使用了十进制数据类型,但我发现小数似乎限制了VBA以指数形式表示的大值。所以我再次搜索了一下,发现这篇文章https://msdn.microsoft.com/en-us/library/ae55hdtk.aspx。正如本文中所述,相当于VBA指数形式的C#数据类型

非整数数量的值可以表示为mmmEeee,其中mmm是 尾数(所述显著位数)和电气和电子设备的指数(一个功率的10 )。非整数类型的最高正值分别为 7.9228162514264337593543950335E + 28(十进制),3.4028235E + 38(单倍)和1.79769313486231570E + 308(双倍)。

这意味着Double数据类型具有最大的值范围。所以现在我很困惑十进制和双精度。

然后我做一个小实验用代码象下面

double dbl = 1.123456789123456789123456789E-28; 
    decimal dcl = 1.123456789123456789123456789E-28M; 
    MessageBox.Show(dbl.ToString()); 
    MessageBox.Show(dcl.ToString()); 

的DBL打印值,因为它是1.123456789123456789123456789E-28而DCL值变为0.0000000000000000000000000001; 有人可以解释这里发生了什么吗?什么是C#中的等效数据类型来表示像VBA中一样精确的大指数值?

+2

我想如果你进一步阅读第一篇文章,你会明白不同之处以及何时使用它们。我想你可能误解了你发布的第一个链接。 – Hank

回答

4

根据C#语言规范:https://msdn.microsoft.com/en-us/library/aa691085%28v=vs.71%29.aspx

  • 的实数被F后缀或f是float类型。例如,文字1f,1.5f,1e10f和123.456F都是浮点类型。
  • D或d后缀的实数字面值是double类型的。例如,文字1d,1.5d,1e10d和123.456D都是double类型。
  • 以M或m为后缀的实数字面值为十进制类型。例如,文字1m,1.5m,1e10m和123.456M都是十进制类型。 通过采用准确的 值将此文字转换为十进制值,如有必要,使用银行家的四舍五入将四舍五入为最接近的可表示值 (第4.1.7节)。 文字中明显的任何比例都将保留,除非值被舍入或值为零 (后者情况下符号和比例将为0)。因此,文字2.900米将被解析为带符号0的小数点, 系数2900和比例3。

纵观第三点,你可以看到那句“... 此实数通过取精确值...转换为十进制值”。您获得的值(0.0000000000000000000000000001)是您开始使用的输入文字(1.123456789123456789123456789E-28M)的转换结果。当然,根据第三个要点的第二部分,如果有必要,转换为“...”的值按照银行家的舍入舍入到最接近的可表示值...“。

对于decimal这是真实的,但对于floatdouble,指数符号可以由数据类型本身保留,所以不需要转换/舍入。

增加:

要在上面进一步扩大,请参见:https://msdn.microsoft.com/en-us/library/364x0z75.aspx

这是decimal数据类型的定义。如上所述:decimal的范围是(-7.9 x 1028 to 7.9 x 1028)/(100 to 28)28 to 29 significant digits。你的文字1.123456789123456789123456789E-28M超出了这个限制,所以当它被转换时,1的右边的所有内容都按上述规则舍入。

解决方案(?):

如果你需要比decimal较大的精度可以提供,你可能想寻找到实现自己的类,它是绝对可行的。考虑寻找想法的C#实现BigDecimal

一个实现我的一个快速谷歌发现:https://gist.github.com/nberardi/2667136

我不能给它的正确性说话,但它至少可以为你的起点。

1

floatdouble是浮点数。这意味着他们分别持有数字和指数系数,其中doublefloat的双倍大小。如果精度很重要,例如价格,建议不要使用double
decimal以“十进制”形式持有数字,并带有固定点。这更精确,特别是使用小数计算。
看起来double更可能是你要找的东西。