我可以说出使用double(或float)而不是decimal的三个优点:

使用较少的内存。 更快是因为浮点数学运算是由处理器原生支持的。 可以表示更大范围的数字。

但这些优势似乎只适用于计算密集型操作,比如在建模软件中发现的那些操作。当然,当需要精度时,不应该使用双精度,例如财务计算。那么,在“正常”应用程序中选择双位数(或浮点数)而不是十进制有什么实际的原因吗?

编辑补充: 谢谢你们的回复,我从他们身上学到了很多。

还有一个问题:一些人认为双数可以更精确地表示实数。当我宣布时,我认为他们通常更准确地代表他们。但是,当执行浮点运算时,精度可能会降低(有时会显著降低),这是真的吗?


当前回答

你似乎完全了解使用浮点类型的好处。我倾向于在所有情况下都为小数进行设计,并依赖于分析器让我知道对小数的操作是否会导致瓶颈或速度减慢。在这些情况下,我将“向下强制转换”为双精度或浮点数,但只在内部执行,并通过限制正在执行的数学运算中的有效数字数量来小心地尝试管理精度损失。

一般来说,如果你的值是瞬态的(没有被重用),使用浮点类型是安全的。浮点类型的真正问题在于以下三种情况。

您正在聚合浮点值(在这种情况下,精度误差会复合) 基于浮点值构建值(例如在递归算法中) 您正在使用非常多的有效数字进行数学运算(例如,123456789.1 * .000000000000000987654321)

EDIT

根据c#小数的参考文档:

关键字decimal表示a 128位数据类型。相比 浮点类型,十进制类型 有更大的精度和更小的 范围,这使得它适用于 财务和货币计算。

为了澄清我上面的说法:

我倾向于设计所有的小数 案件,并依靠一个分析器让 我知道对小数的运算 造成瓶颈或慢速。

我只在偏爱小数的行业工作过。如果您正在处理物理或图形引擎,那么为浮点类型(浮点类型或双浮点类型)进行设计可能更有益。

Decimal不是无限精确的(在基本数据类型中不可能表示非整型的无限精确),但它比double精确得多:

十进制= 28-29位有效数字 Double = 15-16位有效数字 Float = 7位有效数字

编辑2

作为对Konrad Rudolph评论的回应,第一条(上面)绝对是正确的。不精确的聚集确实会产生复合效应。请看下面的示例代码:

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;

还是以投资组合为例:

投资组合中每一行的市场价值都是一种货币价值,可能最好用十进制表示。 投资组合中每一行的权重(=市场价值/ SUM(市场价值))通常用双数表示更好。

当你不需要精度时,使用双浮点数或浮点数,例如,在我编写的平台游戏中,我使用浮点数来存储玩家速度。显然,这里我不需要非常精确,因为我最终舍入为Int在屏幕上绘图。

Decimal具有更宽的字节,CPU原生支持double。十进制是以10为基数的,所以在计算十进制时发生了十进制到双精度的转换。

For accounting - decimal
For finance - double
For heavy computation - double

请记住。net CLR只支持Math.Pow(double,double)。不支持十进制。

.NET Framework 4

[SecuritySafeCritical]
public static extern double Pow(double x, double y);

如果您需要使用其他语言或平台进行二进制查询,那么您可能需要使用float或double,它们是标准化的。