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

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

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

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

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


当前回答

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

其他回答

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

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

您正在聚合浮点值(在这种情况下,精度误差会复合) 基于浮点值构建值(例如在递归算法中) 您正在使用非常多的有效数字进行数学运算(例如,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的结果也没有那么精确(尽管可能会正确舍入),而且浮点数也远没有那么精确,以至于它被简化为只有两位有效数字。

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

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);

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

在某些会计中,考虑使用整型代替或结合使用整型的可能性。例如,假设您操作的规则要求每个计算结果至少前移6位,最终结果将四舍五入到最接近的便士。

A calculation of 1/6th of $100 yields $16.66666666666666..., so the value carried forth in a worksheet will be $16.666667. Both double and decimal should yield that result accurately to 6 decimal places. However, we can avoid any cumulative error by carrying the result forward as an integer 16666667. Each subsequent calculation can be made with the same precision and carried forward similarly. Continuing the example, I calculate Texas sales tax on that amount (16666667 * .0825 = 1375000). Adding the two (it's a short worksheet) 1666667 + 1375000 = 18041667. Moving the decimal point back in gives us 18.041667, or $18.04.

虽然这个简短的示例不会产生使用双位数或小数的累积错误,但可以很容易地展示简单地计算双位数或小数并继续计算会累积重大错误的情况。如果您的操作规则需要有限的小数位数,则将每个值存储为整数,通过乘以10^(所需的小数位数),然后除以10^(所需的小数位数)来获得实际值,将避免任何累积错误。

在不出现小数的情况下(例如,自动售货机),根本没有理由使用非整型。简单地把它想象成数便士,而不是数美元。我曾见过一些代码,其中每次计算都只涉及整个便士,但使用double会导致错误!只有整数数学解决了这个问题。所以我非传统的回答是,如果可能的话,放弃双位数和小数点。