double
(或float
)而非decimal
的优势:
- 占用更少内存。
- 速度更快,因为处理器原生支持浮点数运算。
- 可以表示更大范围的数字。
double
。那么在“正常”应用程序中有没有选择double
(或float
)而非decimal
的实际理由呢?编辑后补充: 感谢您所有出色的回复,我从中学到了很多。
进一步的问题是:有些人认为double可以更准确地表示实数。声明时,我认为它们通常也更准确地表示它们。但是,当执行浮点数运算时,准确性是否会降低(有时显着降低)?
double
(或float
)而非decimal
的优势:
double
。那么在“正常”应用程序中有没有选择double
(或float
)而非decimal
的实际理由呢?我认为你已经很好地总结了优点。然而,你遗漏了一点。 decimal
类型仅在表示 十进制 数字时更准确(例如货币/财务计算中使用的数字)。一般来说,double
类型将提供至少与任意实数相同的精度(如果我错了,请纠正我),并且通常速度更快。简单的结论是:在考虑使用哪种类型时,除非需要 decimal
提供的 十进制
精度,否则始终使用 double
。
编辑:
关于你额外提出的有关浮点数在操作后精度下降的问题,这是一个稍微微妙的问题。确实,在每次操作后,精度(在此处我可互换使用术语)会逐渐降低。这是由于两个原因:
在所有情况下,如果你想比较两个理论上应该是等价的浮点数(但是使用不同的计算方法得出),则需要允许一定程度的容忍度(具体数值有所不同,但通常非常小)。
如果想更详细地了解误差准确性产生的特定情况,请参阅维基百科文章中的准确性部分。最后,如果您想深入了解浮点数/操作在机器级别上的严肃和数学讨论,请尝试阅读备受引用的文章计算机科学家应该了解的浮点运算知识。
Decimal
类型在尾数中有93位精度,而 double
大约只有52位。虽然我希望微软支持IEEE 80位格式,即使它必须填充到16字节;这将允许比 double
或 Decimal
更大的范围,比 Decimal
更快的速度,支持超越运算(例如 sin(x),log(x)等),并且精度虽然不如 Decimal
那么好,但比 double
好得多。 - supercat123456789.1 * .000000000000000987654321
)decimal 关键字表示 128 位数据类型。与浮点类型相比, 小数类型具有更高的精度和较小的 范围,因此适用于金融和货币计算。
因此,为了澄清我上面的说法:在所有情况下,我倾向于设计小数,并依靠分析器告诉我是否在小数上执行操作会导致瓶颈或减速。
我只曾在十进制有利的行业工作过。如果你在物理或图形引擎上工作,为浮点类型(float或double)设计可能会更有益。
十进制不是无限精确的(在原始数据类型中表示非整数的无限精度是不可能的),但它比double要精确得多:
编辑2
针对Konrad Rudolph的评论,第1项(上述)绝对是正确的。不精确性的聚合确实会产生复合效应。请参见下面的代码示例:
private const float THREE_FIFTHS = 3f / 5f;
private const int ONE_MILLION = 1000000;
public static void Main(string[] args)
{
Console.WriteLine("Three Fifths: {0}", THREE_FIFTHS.ToString("F10"));
float asSingle = 0f;
double asDouble = 0d;
decimal asDecimal = 0M;
for (int i = 0; i < ONE_MILLION; i++)
{
asSingle += THREE_FIFTHS;
asDouble += THREE_FIFTHS;
asDecimal += (decimal) THREE_FIFTHS;
}
Console.WriteLine("Six Hundred Thousand: {0:F10}", THREE_FIFTHS * ONE_MILLION);
Console.WriteLine("Single: {0}", asSingle.ToString("F10"));
Console.WriteLine("Double: {0}", asDouble.ToString("F10"));
Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"));
Console.ReadLine();
}
这将输出以下内容:
Three Fifths: 0.6000000000
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 599999.9999886850
Decimal: 600000.0000000000
如您所见,尽管我们从相同的源常量添加,双精度浮点数的结果不够精确(虽然可能会正确四舍五入),而单精度浮点数则远不如此精确,甚至只剩下两位有效数字。
Single: 667660.400000000000
,而十进制值产生了Decimal: 666666.7000000000
。浮点值比正确值少了一千左右。 - jhenninger对于基于10的值,例如财务计算,建议使用十进制。
但是,对于任意计算的值,双精度浮点数通常更准确。
例如,如果您想计算投资组合中每条线路的权重,请使用double,因为结果将更接近100%。
在以下示例中,doubleResult比decimalResult更接近1:
// Add one third + one third + one third with decimal
decimal decimalValue = 1M / 3M;
decimal decimalResult = decimalValue + decimalValue + decimalValue;
// Add one third + one third + one third with double
double doubleValue = 1D / 3D;
double doubleResult = doubleValue + doubleValue + doubleValue;
再举一个投资组合的例子:
投资组合中每条投资线的市场价值是一种货币价值,最好表示为十进制数。
每条投资线的权重(= 市场价值 / SUM(市场价值))通常最好表示为双精度浮点数。
当你不需要精度时,可以使用double或float。例如,在我编写的平台游戏中,我使用float来存储玩家速度。显然,我在这里并不需要超级精度,因为最终会四舍五入为Int以在屏幕上绘制。
由于float和double是二进制数据类型,因此在舍入数字时会出现一些困难和错误,例如double会将0.1舍入为0.100000001490116,double也会将1/3舍入为0.33333334326441。简单地说,并非所有实数都有准确的double类型表示。
幸运的是,C#还支持所谓的十进制浮点算法,其中数字通过十进制数值系统而不是二进制系统表示。因此,十进制浮点算法在存储和处理浮点数时不会失去精度。这使得它非常适合需要高精度计算的场合。
如果您需要与其他语言或平台进行二进制交互,则可能需要使用标准化的float或double类型。
我的观点是,在处理货币和其他需要完全匹配人类计算的情况下,默认使用“decimal”,并且在其他情况下默认选择使用double。
十进制具有更宽的字节,双精度浮点数是CPU本地支持的。 十进制是基于10的,因此在计算十进制时会发生十进制到双精度浮点数的转换。
For accounting - decimal
For finance - double
For heavy computation - double
[SecuritySafeCritical]
public static extern double Pow(double x, double y);