C# 什么时候我应该使用双精度而不是十进制?

C# 什么时候我应该使用双精度而不是十进制?,c#,types,floating-point,double,decimal,C#,Types,Floating Point,Double,Decimal,我可以列举使用double(或float)而不是decimal)的三个优点: 使用更少的内存 更快,因为处理器本机支持浮点数学运算 可以表示更大范围的数字 但这些优势似乎只适用于计算密集型操作,如建模软件中的操作。当然,当需要精度时,例如财务计算,不应使用双倍。那么,在“正常”应用程序中,是否有任何实际理由选择双精度(double)(或float)而不是decimal 编辑以添加: 感谢所有的回复,我从他们身上学到了很多 还有一个问题:一些人指出双倍可以更精确地表示真实数字。当我宣布时,我认为它

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

  • 使用更少的内存
  • 更快,因为处理器本机支持浮点数学运算
  • 可以表示更大范围的数字
  • 但这些优势似乎只适用于计算密集型操作,如建模软件中的操作。当然,当需要精度时,例如财务计算,不应使用双倍。那么,在“正常”应用程序中,是否有任何实际理由选择双精度(
    double
    )(或
    float
    )而不是
    decimal

    编辑以添加: 感谢所有的回复,我从他们身上学到了很多


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

    在不需要精度的情况下使用双精度或浮点,例如,在我编写的platformer游戏中,我使用浮点存储玩家速度。显然,这里不需要超精度,因为我最终会在屏幕上绘制一个整数。

    使用浮点类型的好处似乎让您一目了然。在任何情况下,我都倾向于为小数设计,并依靠探查器让我知道对小数的操作是否会导致瓶颈或减速。在这些情况下,我将“向下转换”为double或float,但仅在内部执行,并通过限制正在执行的数学运算中的有效位数来小心地尝试管理精度损失

    一般来说,如果您的值是瞬态的(不可重用),则可以安全地使用浮点类型。浮点类型的真正问题是以下三种情况

  • 您正在聚合浮点值(在这种情况下,精度错误是复合的)
  • 基于浮点值构建值(例如在递归算法中)
  • 您正在使用大量有效数字进行数学运算(例如,
    123456789.1*.000000000000000 987654321
  • 编辑

    根据报告:

    decimal关键字表示 128位数据类型。与…相比 浮点类型,十进制类型 具有更高的精度和更小的 范围,使其适合 金融和货币计算

    为了澄清我的上述声明:

    我倾向于设计所有的小数 案例,并依靠探查器让 告诉我十进制运算是否正确 导致瓶颈或减速

    我只在小数有利的行业工作过。如果您使用的是phsyics或图形引擎,那么为浮点类型(float或double)进行设计可能会更加有益

    十进制不是无限精确的(对于原始数据类型中的非整数,不可能表示无限精度),但它远比double精确:

    • 十进制=28-29位有效数字
    • 双精度=15-16位有效数字
    • 浮点=7位有效数字
    编辑2

    作为对女士评论的回应,第#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();
    }
    

    正如您所看到的,即使我们从同一个源常量进行加法,double的结果也不太精确(尽管可能会正确舍入),而float的精度也远低于double,以至于它被减少到只有两个有效数字。

    我认为您已经很好地总结了优点。不过,你遗漏了一点。该类型仅在表示以10为基数的数字时更准确(例如,货币/金融计算中使用的数字)。一般来说,对于任意实数,该类型将提供至少同样高的精度(如果我错了,有人会纠正我)和更高的速度。简单的结论是:在考虑使用哪个时,始终使用
    double
    ,除非您需要
    base 10
    所提供的
    decimal
    精度

    编辑:

    关于操作后浮点数精度下降的问题,这是一个稍微微妙的问题。事实上,每次操作完成后,精度(我在这里互换使用术语表示精度)将稳步下降。这是由于两个原因:

  • 事实上,某些数字(最明显的是小数)不能真正以浮点形式表示
  • 四舍五入错误会发生,就像手工计算一样。然而,这些错误是否严重到值得深思,这在很大程度上取决于上下文(您执行了多少操作) 在所有情况下,如果您想要比较理论上应该相等的两个浮点数(但使用不同的计算得出),则需要允许一定程度的公差(变化程度不同,但通常非常小)


    有关可引入精度误差的特定情况的更详细概述,请参阅。最后,如果您想在机器级别上对浮点数/运算进行深入(数学)的讨论,请阅读经常引用的文章。

    如果您需要与其他语言或平台进行二进制交互,则可能需要使用float或double,它们是标准化的。

    如果您看重性能而不是正确性,请使用浮点。

    选择应用程序功能中的类型。如果你需要像财务分析那样的精确性,你已经回答了你的问题。但是如果你的申请可以通过
    Three Fifths: 0.6000000000
    Six Hundred Thousand: 600000.0000000000
    Single: 599093.4000000000
    Double: 599999.9999886850
    Decimal: 600000.0000000000
    
    // 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;
    
    For accounting - decimal
    For finance - double
    For heavy computation - double
    
    [SecuritySafeCritical]
    public static extern double Pow(double x, double y);