关于C#:如何决定使用什么-double or decimal

How to decide what to use - double or decimal?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
decimal vs double! - Which one should I use and when?

我在我的交易软件中使用double类型作为价格。我注意到有时会有一些奇怪的错误。如果价格在"点"后包含4位数字,例如2.1234,则会出现这种情况。

当我从我的程序"2.1234"发送时,市场订单以"2.1235"的价格出现。

我不使用decimal,因为我不需要"极端"的精度。我不需要区分"2.00000000003"和"2.00000000002"。我最多需要一个点后6位数字。

问题是-线路在哪里?何时使用decimal

我应该使用decimal进行任何金融操作吗?即使我只需要点后一个数字?(1.1 1.2等)

我知道decimal相当慢,所以我宁愿使用double,除非绝对需要decimal


无论何时处理希望(并且可以)以10为基数精确表示的数量,都要使用十进制。这包括货币价值,因为您希望2.1234精确表示为2.1234。

当您不需要在Base-10中精确表示时,请使用Double。这通常有利于处理测量,因为这些已经是近似值,而不是确切的数量。

当然,如果以10为基数的精确表示对您不重要,则会考虑其他因素,根据具体情况,这些因素可能重要,也可能不重要:

  • 双精度具有较大的范围(可以处理非常大和非常小的幅度);
  • 小数精度更高(有效位数更高);
  • 您可能需要使用double与一些不知道decimal的旧API进行交互;
  • double比decimal快;
  • 十进制有更大的内存占用;


当需要准确度和重要性时,使用decimal

当精度不那么重要时,可以使用double

在您的案例中,您应该使用decimal作为财务事项。


对于财务操作,我总是使用十进制类型


使用decimal,它是为代表10口井的能力而建造的(即价格)。


在这个例子中有一个简单的响应:

1
2
3
4
decimal d = 0.3M+0.3M+0.3M;
            bool ret = d == 0.9M; // true
            double db = 0.3 + 0.3 + 0.3;
            bool dret = db == 0.9; // false

使用double的测试失败,因为0.3的二进制表示(以2为基数)是周期性的,所以您的精度很低,十进制是用bcd表示的,所以以10为基数,并且您没有意外地松脱有效数字。不幸的是,十进制比双精度慢得多。通常,我们在财务计算中使用小数,其中任何数字都必须考虑以避免公差,工程计算采用双/浮点数。


如果是金融软件,你应该使用十进制。这篇wiki文章总结得很好。


小数是处理价格的方法。


在msdn上有一个解释


double是一种通用的浮点数据类型,decimal专门用于货币和金融领域。尽管double通常只起作用,但在某些情况下(例如,当达到数十亿的值时,舍入错误)小数位可能会避免出现问题。


如果你总是知道你将拥有的最大小数位数(小数点后的数字)。那么最好的做法是使用定点表示法。这将给你一个准确的结果,同时仍然工作非常快。

使用定点的最简单方法是简单地将数字存储在1000个部分的整数中。例如,如果价格总是有2个小数,那么您将节省美分的金额(12.45美元存储在一个值为1245的int中,因此它代表1245美分)。使用四个小数,您将存储一万个(12.3456将存储在一个值为123456(代表123456万分之一)的int中)等。

这样做的缺点是,如果将两个值相乘(0.1 * 0.1 = 0.01,而1 * 1 = 1,则单位从十分之一变为百分之一,则有时需要进行转换。如果你要使用其他的数学函数,你也必须考虑到类似的事情。

另一方面,如果小数的数量变化很大,使用固定点是一个坏主意。如果需要高精度的浮点计算,那么十进制数据类型就是为此而构建的。


一旦开始计算双精度数,可能会遇到意外的舍入问题,因为双精度数使用数字的二进制表示,而十进制数使用保留小数位数的十进制表示。这可能就是你所经历的。如果只对文本或数据库的双精度进行序列化和反序列化,而不进行任何取整,则实际上不会失去任何精度。

然而,小数更适合于表示关心十进制数字的货币值(而不是双精度数在内部使用的二进制数字)。但是,如果需要进行复杂的计算(例如,精算计算中使用的积分),则在进行计算之前,必须将小数转换为双精度,这会抵消使用小数的优点。

小数还"记住"它有多少个数字,例如,即使小数1.230等于1.23,第一个数字仍然知道尾随的零,如果格式化为文本,则可以显示它。