.net NET中十进制、浮点和双精度之间的差异?

.net NET中十进制、浮点和双精度之间的差异?,.net,floating-point,double,decimal,.net,Floating Point,Double,Decimal,在.NET中,decimal、float和double之间有什么区别 什么时候会有人使用其中一种?精度是主要区别 -7位(32位) -15-16位(64位) -28-29位有效数字(128位) 小数具有更高的精度,通常用于要求高精度的金融应用程序中。小数比双精度/浮点数慢得多(在某些测试中高达20倍) 小数和浮点数/双精度不能在没有强制转换的情况下进行比较,而浮点数和双精度可以进行比较。小数也允许编码或尾随零 float flt = 1F/3; double dbl = 1D/3; decima

在.NET中,
decimal
float
double
之间有什么区别


什么时候会有人使用其中一种?

精度是主要区别

-7位(32位)

-15-16位(64位)

-28-29位有效数字(128位)

小数具有更高的精度,通常用于要求高精度的金融应用程序中。小数比双精度/浮点数慢得多(在某些测试中高达20倍)

小数和浮点数/双精度不能在没有强制转换的情况下进行比较,而浮点数和双精度可以进行比较。小数也允许编码或尾随零

float flt = 1F/3;
double dbl = 1D/3;
decimal dcm = 1M/3;
Console.WriteLine("float: {0} double: {1} decimal: {2}", flt, dbl, dcm);
结果:

float: 0.3333333  
double: 0.333333333333333  
decimal: 0.3333333333333333333333333333

float
double
是。换句话说,它们代表如下数字:

10001.10010110011
12345.65789
二进制数和二进制点的位置都在值内编码

decimal
是一个数字。换句话说,它们代表如下数字:

10001.10010110011
12345.65789
同样,小数点的数字和位置都在值中编码–这就是为什么
decimal
仍然是浮点类型而不是定点类型

需要注意的重要一点是,人类习惯于以十进制形式表示非整数,并期望以十进制表示的精确结果;并非所有的十进制数都可以用二进制浮点表示,例如0.1,所以如果使用二进制浮点值,实际上可以得到0.1的近似值。当使用浮点小数点时,仍然会得到近似值–例如,1除以3的结果无法精确表示

关于在以下情况下使用什么:

  • 对于“自然精确小数”的值,最好使用
    decimal
    。这通常适用于人类发明的任何概念:金融价值是最明显的例子,但也有其他例子。考虑到潜水员或溜冰运动员的得分,例如:


  • 对于那些更为自然产物的值,而这些值无论如何都无法准确测量,
    float
    /
    double
    更为合适。例如,科学数据通常以这种形式表示。在这里,原始值一开始就不是“小数精度”,因此保持“小数精度”对预期结果并不重要。使用浮点二进制点类型比使用小数要快得多

  • Double和float可以被整数零除,在编译和运行时都不会出现异常
  • 小数不能被整数零除。如果这样做,编译将始终失败

  • 十进位结构严格适用于要求精确的财务计算,这相对不允许四舍五入。但是,小数不足以用于科学应用,原因如下:

    • 在许多科学计算中,由于被测量的物理问题或人工制品的实际限制,一定程度的精度损失是可以接受的。在金融领域,精度损失是不可接受的
    • 对于大多数操作,十进制比浮点和双精度运算慢得多,主要是因为浮点运算是在二进制中完成的,而十进制是在10进制中完成的(即浮点和双精度运算由FPU硬件处理,如MMX/SSE,而小数是在软件中计算的)
    • Decimal的值范围比double小得令人无法接受,尽管它支持更多的精度数字。因此,十进制不能用来表示许多科学值

    float
    7位精度

    double
    大约有15位精度

    decimal
    大约有28位精度

    如果您需要更高的精度,请使用double而不是float。 在现代CPU中,两种数据类型的性能几乎相同。使用float的唯一好处是它们占用更少的空间。事实上,只有当你拥有很多的时候才有意义


    我发现这很有趣

    这对我来说是一条有趣的线索,因为今天,我们刚刚遇到了一个令人讨厌的小错误,
    decimal
    的精度低于
    float

    在C#代码中,我们从Excel电子表格中读取数值,将其转换为
    十进制
    ,然后将该
    十进制
    发送回服务以保存到SQL Server数据库中

    Microsoft.Office.Interop.Excel.Range cell = …
    object cellValue = cell.Value2;
    if (cellValue != null)
    {
        decimal value = 0;
        Decimal.TryParse(cellValue.ToString(), out value);
    }
    
    现在,对于我们几乎所有的Excel值,这都非常有效。但是对于一些非常小的Excel值,使用decimal.TryParse完全丢失了值。其中一个例子是

    • cellValue=0.00006317592

    • Decimal.TryParse(cellValue.ToString(),out值);//将返回0

    奇怪的是,解决方案是先将Excel值转换为
    双精度
    ,然后再转换为
    十进制

    Microsoft.Office.Interop.Excel.Range cell = …
    object cellValue = cell.Value2;
    if (cellValue != null)
    {
        double valueDouble = 0;
        double.TryParse(cellValue.ToString(), out valueDouble);
        decimal value = (decimal) valueDouble;
        …
    }
    
    尽管双精度的精度低于十进制,但这实际上确保了小数字仍能被识别。出于某种原因,
    double.TryParse
    实际上能够检索如此小的数字,而
    decimal.TryParse
    会将它们设置为零


    奇怪。非常奇怪。

    如前所述,整数是整数。他们无法存储点,比如.7、.42和.007。如果需要存储非整数的数字,则需要不同类型的变量。您可以使用double类型或float类型。您以完全相同的方式设置这些类型的变量:不使用单词
    int
    ,而是键入
    double
    float
    。像这样:

    float myFloat;
    double myDouble;
    
    float
    是“浮点”的缩写,只是指一个数字的末尾有一个点。)

    区别
    myDouble = 0.007;
    myDouble = 12345678.1234567;
    
    +---------+----------------+---------+----------+---------------------------------------------------------+
    | C#      | .Net Framework | Signed? | Bytes    | Possible Values                                         |
    | Type    | (System) type  |         | Occupied |                                                         |
    +---------+----------------+---------+----------+---------------------------------------------------------+
    | sbyte   | System.Sbyte   | Yes     | 1        | -128 to 127                                             |
    | short   | System.Int16   | Yes     | 2        | -32,768 to 32,767                                       |
    | int     | System.Int32   | Yes     | 4        | -2,147,483,648 to 2,147,483,647                         |
    | long    | System.Int64   | Yes     | 8        | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
    | byte    | System.Byte    | No      | 1        | 0 to 255                                                |
    | ushort  | System.Uint16  | No      | 2        | 0 to 65,535                                             |
    | uint    | System.UInt32  | No      | 4        | 0 to 4,294,967,295                                      |
    | ulong   | System.Uint64  | No      | 8        | 0 to 18,446,744,073,709,551,615                         |
    | float   | System.Single  | Yes     | 4        | Approximately ±1.5e-45 to ±3.4e38                       |
    |         |                |         |          |  with ~6-9 significant figures                          |
    | double  | System.Double  | Yes     | 8        | Approximately ±5.0e-324 to ±1.7e308                     |
    |         |                |         |          |  with ~15-17 significant figures                        |
    | decimal | System.Decimal | Yes     | 16       | Approximately ±1.0e-28 to ±7.9e28                       |
    |         |                |         |          |  with 28-29 significant figures                         |
    | char    | System.Char    | N/A     | 2        | Any Unicode character (16 bit)                          |
    | bool    | System.Boolean | N/A     | 1 / 2    | true or false                                           |
    +---------+----------------+---------+----------+---------------------------------------------------------+
    
    decimal myNumber = decimal.MaxValue;
    myNumber += 1;
    
    float myNumber = float.MaxValue;
    myNumber += 1;
    
    double myNumber = double.MaxValue;
    myNumber += 1;
    
    Dim fMean as Double = 1.18
    Dim fDelta as Double = 0.08
    Dim fLimit as Double = 1.1
    
    If fMean - fDelta < fLimit Then
        bLower = True
    Else
        bLower = False
    End If
    
    BINARY or COMP like float or double or decimal
    PACKED-DECIMAL or COMP-3 (2 digit in 1 byte)
    ZONED-DECIMAL (1 digit in 1 byte) 
    
    /==========================================================================================
        Type       Bits    Have up to                   Approximate Range 
    /==========================================================================================
        float      32      7 digits                     -3.4 × 10 ^ (38)   to +3.4 × 10 ^ (38)
        double     64      15-16 digits                 ±5.0 × 10 ^ (-324) to ±1.7 × 10 ^ (308)
        decimal    128     28-29 significant digits     ±7.9 x 10 ^ (28) or (1 to 10 ^ (28)
    /==========================================================================================
    
    Decimal dec = 12M/6;
    Double dbl = 11D/6;
    float fl = 15F/6;
    
    Float - 4
    Double - 8
    Decimal - 12