在.NET中,十进制、浮点和双精度之间有什么区别?

什么时候有人会用这些?


精度是主要区别。

浮点-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(System.Single的C#别名)和double(System.double的C#别名。float为32位;double是64位。换句话说,它们表示如下数字:

10001.10010110011

二进制数和二进制点的位置都在值中编码。

decimal(System.decimal的C#别名)是浮点小数点类型。换句话说,它们表示如下数字:

12345.65789

同样,小数点的数字和位置都编码在值中——这使得小数点仍然是浮点类型而不是定点类型。

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

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

对于“自然精确小数”的值,最好使用小数。这通常适用于人类发明的任何概念:财务价值是最明显的例子,但也有其他例子。例如,考虑给潜水员或滑冰运动员的分数。对于那些本质上更为人为的、无论如何都无法精确测量的值,浮点/双精度更为合适。例如,科学数据通常以这种形式表示。在这里,原始值从一开始就不是“小数精度”的,因此对于预期结果来说,保持“小数精度精度”并不重要。浮点二进制点类型比小数更快。


Double和float可以被整数零除,在编译和运行时都没有异常。小数不能除以整数零。如果你这样做,编译总是会失败。


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

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


浮点7位精度

双精度约为15位

十进制大约有28位精度

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

我觉得这很有趣。每个计算机科学家都应该知道浮点运算


这对我来说是一个有趣的线索,因为今天,我们刚刚遇到了一个令人讨厌的小错误,关于十进制比浮点精度低。

在我们的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完全丢失了值。一个这样的例子是

单元格值=0.00006317592Decimal.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的精度低于十进制,这实际上确保了小数字仍然可以被识别。由于某种原因,double.TryParse实际上能够检索这样的小数字,而decimal.TryPars将它们设置为零。

古怪的非常奇怪。


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

float myFloat;
double myDouble;

(float是“浮点”的缩写,意思是一个末尾有点的数字。)

两者的区别在于它们所能容纳的数字的大小。对于浮点数,您的数字最多可以有7位。对于双打,最多可以有16位数字。更准确地说,这里是官方尺寸:

float:  1.5 × 10^-45  to 3.4 × 10^38  
double: 5.0 × 10^-324 to 1.7 × 10^308

float是32位数字,double是64位数字。

双击新按钮以获取代码。在按钮代码中添加以下三行:

double myDouble;
myDouble = 0.007;
MessageBox.Show(myDouble.ToString());

停止程序并返回编码窗口。更改此行:

myDouble = 0.007;
myDouble = 12345678.1234567;

运行程序并单击双击按钮。消息框正确显示数字。不过,在末尾添加另一个数字,C#将再次向上或向下舍入。寓意是,如果你想要准确,请小心四舍五入!


+---------+----------------+---------+----------+---------------------------------------------------------+
| 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                                           |
+---------+----------------+---------+----------+---------------------------------------------------------+

请参阅此处了解更多信息。


浮动:±1.5 x 10^-45至±3.4 x 10^38(~7个有效数字双倍:±5.0 x 10^-324至±1.7 x 10^308(15-16个有效数字)小数:±1.0 x 10^-28至±7.9 x 10^28(28-29个有效数字)


对于游戏和嵌入式系统等内存和性能都至关重要的应用程序,浮点运算通常是数字类型的选择,因为它速度更快,大小只有双倍运算的一半。整数曾经是首选的武器,但在现代处理器中,浮点性能已经超过了整数。十进制是正确的!


Decimal、Double和Float变量类型在存储值的方式上有所不同。精度是主要区别,其中float是单精度(32位)浮点数据类型,double是双精度(64位)浮点类型,decimal是128位浮点数据类型。

浮点-32位(7位)

双64位(15-16位)

十进制-128位(28-29位有效数字)

有关…的详细信息。。。十进制、浮点和双精度之间的差异


每种方法的主要区别在于精度。

float是32位数字double是64位数字十进制是128位数字


没有人提到

在默认设置中,Floats(System.Single)和doubles(System.Double)永远不会使用Decimal(System.Decimal)将始终使用溢出检查。

我是说

decimal myNumber = decimal.MaxValue;
myNumber += 1;

引发OverflowException。

但这些并不:

float myNumber = float.MaxValue;
myNumber += 1;

&

double myNumber = double.MaxValue;
myNumber += 1;

我不会重复在其他回答和评论中已经回答的大量好的(和一些坏的)信息,但我会用提示回答您的后续问题:

什么时候有人会用这些?

对计数值使用十进制

测量值使用浮点/双精度

一些示例:

钱(我们是数钱还是量钱?)距离(我们是计算距离还是测量距离?*)分数(我们是计算分数还是衡量分数?)

我们总是数钱,不应该量钱。我们通常测量距离。我们经常计算分数。

*在某些情况下,我称之为名义距离,我们可能确实需要“计算”距离。例如,也许我们正在处理显示到城市距离的国家标志,我们知道这些距离永远不会超过一个十进制数字(xxx.x km)。


所有这些类型的问题是存在一定的不精确性而且这个问题可能发生在小的小数上,如下面的例子

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

问题:bLower变量包含哪个值?

答案:在32位机器上,bLower包含TRUE!!!

如果我将Double替换为Decimal,bLower包含FALSE,这是一个好答案。

在double中,问题是fMean fDelta=1.09999999999,低于1.1。

注意:我认为同样的问题肯定会出现在其他数字上,因为十进制只是精度更高的双精度,而且精度总是有限制的。

事实上,Double、Float和Decimal对应于COBOL中的二进制十进制!

很遗憾,在.Net中不存在COBOL中实现的其他数字类型

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) 

简单地说:

Decimal、Double和Float变量类型在存储值的方式上有所不同。精度是主要区别(请注意,这不是唯一的区别),其中float是单精度(32位)浮点数据类型,double是双精度(64位)浮点类型,decimal是128位浮点数据类型。汇总表:

/==========================================================================================类型钻头达到近似范围/==========================================================================================浮动32位7位数-3.4×10^(38)到+3.4×10^双64 15-16位数字±5.0×10^(-324)至±1.7×10^十进制128 28-29有效数字±7.9 x 10^(28)或(1至10^(29)/==========================================================================================你可以在这里阅读更多,浮点,双精度和十进制。


在.Net(c#)中定义十进制、浮点和双精度

您必须将值提到为:

Decimal dec = 12M/6;
Double dbl = 11D/6;
float fl = 15F/6;

并检查结果。

每个占用的字节为

Float - 4
Double - 8
Decimal - 12

浮动:

它是一个浮点二进制点类型变量。这意味着它以二进制形式表示数字。浮点是一种单精度32位(6-9位有效数字)数据类型。它主要用于图形库,因为对处理能力的要求非常高,也用于舍入误差不太重要的情况。

双倍:

它也是一个具有双精度和64位大小(15-17位有效数字)的浮点二进制点类型变量。Double可能是真实值最常用的数据类型,但金融应用程序和需要高精度的地方除外。

十进制的:

它是一个浮点型变量。这意味着它使用十进制数字(0-9)表示数字。它使用128位(28-29位有效数字)来存储和表示数据。因此,它比浮点和双精度更高。由于它们的高精度和易于避免舍入误差,它们主要用于金融应用。

例子:

using System;
  
public class GFG {
  
    static public void Main()
    {
  
        double d = 0.42e2;    //double data type
        Console.WriteLine(d); // output 42
  
        float f = 134.45E-2f;  //float data type
        Console.WriteLine(f); // output: 1.3445
  
        decimal m = 1.5E6m;   //decimal data type
        Console.WriteLine(m); // output: 1500000
    }
}

浮点、双精度和十进制之间的比较基于:

使用的位数:

浮点使用32位表示数据。Double使用64位表示数据。十进制使用128位表示数据。

数值范围:

浮动值范围约为±1.5e-45至±3.4e38。双倍值范围约为±5.0e-324至±1.7e308。十进制值的范围约为±1.0e-28至±7.9e28。

精度:

浮点以单精度表示数据。双精度表示数据。十进制比浮点和双精度更高。

准确度:

浮点运算不如双精度和小数精度高。双精度比浮点精度高,但比十进制精度低。十进制比浮点和双精度更精确。