提问



.NET中decimalfloatdouble有什么区别?


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

最佳参考


floatdouble是浮点二进制点类型。换句话说,它们代表了这样的数字:[55]


10001.10010110011


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


decimal是一个浮点十进制点类型。换句话说,它们代表了这样的数字:[56]


12345.65789


同样,十进制点的数量和位置都在值内编码 - 这使得decimal仍然是浮点类型而不是固定点类型。


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


至于什么时候使用:



  • 对于天然精确小数的值,使用decimal很好。这通常适用于人类发明的任何概念:财务价值是最明显的例子,但也有其他概念。例如,给予潜水员或滑冰者的分数。

  • 对于那些无法完全测量精确的自然人工制品的数值,float/double更合适。例如,科学数据通常会以这种形式表示。这里,原始值不会小数精确到开头,因此保持十进制精度对预期结果并不重要。浮动二进制点类型的工作要快得多超过小数。


其它参考1


精度是主要的区别。


浮点数 - 7位数(32位)[57]


双15-16位(64位)[58]


小数-28-29有效数字(128位)[59]


小数具有更高的精度,通常用于需要高精度的金融应用程序中。小数比一个双/浮点慢得多(在某些测试中高达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

其它参考2


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



  • 由于物理问题或测量的人工制品的实际限制,在许多科学计算中可以接受一定的精度损失。金融业无法接受精确度的损失。

  • 对于大多数操作,十进制比浮动(和多)慢很多(主要是因为浮点运算以二进制完成),而十进制填充是在基数10中完成的(即浮点数和双精度由FPU硬件处理,例如MMX/SSE,而小数用软件计算。)

  • 尽管它支持更多的精度数字,但是Decimal的值范围比double小得多。因此,十进制不能用于表示许多科学价值。


其它参考3





有关更多信息,您可以访问此图片的来源:


http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/921a8ffc-9829-4145-bdc9-a96c1ec174a5[60]

其它参考4


float 7位精度


double有大约15位数的精度


decimal具有大约28位精度


如果您需要更高的精确度,请使用double而不是float。
在现代CPU中,两种数据类型具有几乎相同的性能。使用浮动的唯一好处是它们占用的空间更少。只有当你有很多这样的事情时才真正重要。


我发现这很有趣。每个计算机科学家应该知道浮点运算[61]

其它参考5


没有人提到这一点



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



我的意思是


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


抛出 OverflowException


但这些不是:


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


&安培;


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

其它参考6



  1. Double和float可以除以整数零,在编译和运行时都没有异常。

  2. 十进制不能除以整数零。如果你这样做,编译总是会失败。


其它参考7


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



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



计算的值使用小数


对于测量的值,请使用float/double


一些例子:



  • 钱(我们数钱还是衡量金钱?)

  • 距离(我们计算距离或测量距离吗?*)

  • 得分(我们计算分数还是衡量分数?)



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


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

其它参考8


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


浮动 - 32位(7位)


双 - 64位(15-16位)


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


主要区别是Floats和Doubles是二进制浮点类型,Decimal将值存储为浮点小数点类型。因此,小数具有更高的精度,通常用于需要高精度的货币(金融)或科学计算应用中。但在性能方面,Decimals比double和float类型慢。


十进制可以100%准确地表示十进制格式精度内的任何数字,而Float和Double则无法准确表示所有数字,甚至是各自格式精度的数字。


十进制


在财务应用或科学计算的情况下,最好使用十进制类型,因为它可以提供高水平的准确性并且易于避免舍入误差





除处理货币外,双类型可能是实际值最常用的数据类型。


浮动


它主要用于图形库,因为对处理能力的要求非常高,也使用了可以承受舍入误差的情况。

其它参考9


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


float myFloat;
double myDouble;


(float是浮点数的缩写,只是表示最后有一个点的数字。)


两者之间的差异在于它们可以容纳的数字的大小。对于float,您的号码最多可以包含7位数字。对于double s,最多可以有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#将再次向上或向下舍入。道德是如果你想要准确,小心四舍五入!

其它参考10


这对我来说是一个有趣的线索,因为今天,我们只有一个令人讨厌的小虫,关于decimal精度低于float


在我们的C#代码中,我们从Excel电子表格中读取数值,将它们转换为decimal,然后将此decimal发送回服务以保存到 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 value); //将返回 0



奇怪的是,解决方案是首先将Excel值转换为double,然后转换为decimal:


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的精度低于decimal,但实际上确保了小数字仍然可以识别。出于某种原因, double.TryParse 实际上能够检索到这么小的数字,而 decimal.TryParse 会将它们设置为零。


奇。很奇怪。

其它参考11


漂浮〜±1.5 x 10-45到±3.4 x 1038 -------- 7个数字

double~±5.0 x 10-324到±1.7 x 10308 ------ 15或16个数字

十进制〜±1.0 x 10-28到±7.9 x 1028 -------- 28或29个数字


其它参考12


对于内存和性能都很关键的游戏和嵌入式系统等应用程序,float通常是数字类型,因为它更快,是double的一半大小。整数曾经是首选武器,但浮点性能在现代处理器中已超过整数。十进制就出来了!

其它参考13


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


浮动 - 32位(7位)


双 - 64位(15-16位)


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


更多关于......十进制,浮点数和双数[62]之间的区别

其它参考14


所有这些类型的问题在于存在某种不精确性
并且,如下例所示,小的十进制数可能会出现此问题


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!


如果我用Decimal替换Double,则bLower包含FALSE,这是一个很好的答案。


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


注意:我认为同样的问题肯定存在于其他数字,因为Decimal只是一个具有更高精度的双精度,并且精度始终是一个限制。


实际上,Double,Float和Decimal对应于COBOL中的BINARY十进制!


遗憾的是,COBOL中实现的其他数字类型不存在于.Net中。对于那些不了解COBOL的人来说,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) 

其它参考15


这些中的每一个之间的主要区别在于精度。


float32-bit数,double64-bit数,decimal128-bit数。

其它参考16


简单来说:



  1. Decimal,Double和Float变量类型在存储值方面有所不同。

  2. 精度是 主要区别 (请注意,这不是单一的区别) float 是单精度(32位)浮动点数据类型, double 是双精度(64位)浮点数据类型,十进制是128位浮点数据类型。

  3. 摘要表:



/==========================================================================================
    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)
/==========================================================================================

你可以在这里阅读更多内容,Float,Double和Decimal。[63] [64] [65] [66]