什么时候应该使用double而不是小数?
我可以列举使用double
(或float
)而不是decimal
三个优点:
但是这些优势似乎仅适用于计算密集型操作,如建模软件中的那些。 当然,如果需要精确度,例如财务计算,则不应使用双打。 那么是否有任何实际的理由在“正常”应用程序中选择double
(或float
)而不是decimal
?
编辑补充:感谢所有的伟大回应,我从他们身上学到了。
还有一个问题:有些人认为双打可以更精确地表示实数。 当宣布时,我会认为他们通常会更准确地代表他们。 但是,当浮点运算执行时,准确度可能会降低(有时显着),这是否是一个真实的陈述?
我认为你已经很好地总结了这些优势。 然而你错过了一点。 decimal
类型只能代表基数为10的数字(例如在货币/财务计算中使用的数字)。 一般来说, double
类型将提供至少同样精确度(如果我错了,有人会纠正我),对于任意实数,速度肯定会更快。 简单的结论是:在考虑使用哪一种时,除非需要decimal
提供的base 10
精度,否则总是使用double
精度。
编辑:
关于操作后浮点数精度下降的额外问题,这是一个稍微更微妙的问题。 事实上,每次操作完成后,精度(我在这里使用术语“可互换”来表示准确度)会稳步下降。 这是由于两个原因:a)某些数字(最明显的小数)不能以浮点形式真实地表示,b)发生舍入误差,就像您手动进行计算一样。 它很大程度上取决于上下文(您正在执行多少操作),但是这些错误是否足够重要,以致需要考虑很多问题。 在所有情况下,如果要比较理论上应该等价的两个浮点数(但是使用不同的计算),则需要允许一定程度的容差(多少变化,但通常非常小) 。
有关可以引入精度错误的特定情况的更详细概述,请参阅维基百科文章的精确度部分。 最后,如果您希望在机器级对浮点数/操作进行认真深入的(和数学的)讨论,请阅读经常引用的文章每个计算机科学家应该了解的浮点运算。
您似乎很清楚使用浮点类型的好处。 我倾向于在所有情况下设计小数点,并依靠分析器让我知道小数点操作是否会导致瓶颈或减速。 在这些情况下,我会“下注”来双倍或浮动,但只能在内部完成,并且仔细尝试通过限制正在执行的数学运算中的有效数字的数量来管理精度损失。
一般来说,如果你的值是瞬态的(不重用),你可以安全地使用浮点类型。 浮点类型的真正问题是以下三种情况。
123456789.1 * .000000000000000987654321
) 编辑
根据关于C#小数点的参考文档:
decimal关键字表示128位数据类型。 与浮点类型相比,小数类型具有更高的精度和更小的范围,因此适用于财务和货币计算。
为了澄清我的上述说法:
我倾向于在所有情况下设计小数点,并依靠分析器让我知道小数点操作是否会导致瓶颈或减速。
我只在有小数的行业工作过。 如果您正在使用phsyics或图形引擎,那么设计浮点类型(float或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
正如你所看到的,尽管我们是从相同的源常量添加的,但double的结果不太精确(尽管可能会正确舍入),并且浮点数精确度要低得多,直到它减少到只有两位有效数字。
像其他人所建议的那样,对基数10的值使用小数,例如财务计算。
但是double对于任意计算值通常更准确。
例如,如果您要计算投资组合中每条线的权重,请使用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;
所以再次以投资组合为例:
投资组合中每一行的市场价值都是货币价值,可能最好用十进制表示。
投资组合中每条线的权重(=市场价值/总和(市场价值))通常更好地表示为双倍。
上一篇: When should I use double instead of decimal?
下一篇: Calculation result is different depending on decimal or double