是什么区别decimal
,float
并double
在.NET?
有人什么时候会使用其中之一?
是什么区别decimal
,float
并double
在.NET?
有人什么时候会使用其中之一?
Answers:
float
和double
是浮点型二进制点类型。换句话说,它们代表这样的数字:
10001.10010110011
二进制数和二进制点的位置都编码在该值内。
decimal
是浮点小数点类型。换句话说,它们代表这样的数字:
12345.65789
同样,小数点的数字和位置都被编码在该值之内,这decimal
仍然是浮点类型而不是定点类型。
需要注意的重要一点是,人类习惯于以十进制形式表示非整数,并期望以十进制表示形式得到准确的结果。并非所有十进制数字都可以在二进制浮点数中精确表示(例如0.1),因此,如果您使用二进制浮点数,则实际上将近似为0.1。当使用浮点小数点时,您仍然会得到近似值-例如,不能精确表示1除以3的结果。
至于什么时候使用:
对于“自然精确的小数”值,最好使用decimal
。这通常适用于人类发明的任何概念:财务价值是最明显的例子,但也有其他一些例子。例如,考虑给潜水员或溜冰者的分数。
如果读入的性质的更加伪影不能真正测量值准确反正float
/ double
更合适。例如,科学数据通常以这种形式表示。在这里,原始值一开始就不会是“十进制精度”,因此对于预期结果而言,保持“十进制精度”并不重要。浮点二进制点类型比十进制小得多。
float
/ double
平时并不代表数字作为101.101110
,通常它被表示为类似1101010 * 2^(01010010)
-指数
float
是一个C#别名关键字,并且不是.Net类型。它是System.Single
.. single
并且double
是浮动二进制点类型。
精度是主要区别。
浮点数 -7位数字(32位)
双 -15-16位数字(64位)
十进制 -28-29有效数字(128位)
小数位数具有更高的精度,通常在要求高度准确性的金融应用程序中使用。小数要比double / float慢得多(在某些测试中,多达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
0.1
-在现实世界中很少有这种情况! 任何有限的存储格式都会将无限数量的可能值与有限数量的位模式混淆。例如,float
将合并0.1
和0.1 + 1e-8
,而decimal
将合并0.1
和0.1 + 1e-29
。当然,在给定范围内,某些值可以以零损失的精度以任何格式表示(例如,float
可以以零损失的精度存储高达1.6e7的任何整数)-但这仍然不是无限的精度。
0.1
是不是一个特殊的价值!唯一使之0.1
比“更好”的0.10000001
是,因为人类喜欢以10为底。即使使用一个float
值,如果您以0.1
相同的方式初始化两个值,它们将都是相同的值。只是该值不会完全相同 0.1
-它是最接近的值0.1
,可以精确地表示为float
。当然,使用二进制浮点数,(1.0 / 10) * 10 != 1.0
但也使用十进制浮点数(1.0 / 3) * 3 != 1.0
。 两者都不是完全精确的。
double a = 0.1; double b = 0.1;
那么a == b
会是真的。只是,a
和b
将两者并不完全一样0.1
。在C#中,如果你这样做decimal a = 1.0m / 3.0m; decimal b = 1.0m / 3.0m;
,然后a == b
也将是如此。但是,在这种情况下,既不的a
,也不b
将正好等于1/3
-他们都将相等0.3333...
。在这两种情况下,都会由于表示而损失一些准确性。您固执地说这decimal
具有“无限”的精度,这是错误的。
十进制结构严格适合需要准确性的财务计算,而这些准确性相对不能四舍五入。但是,由于以下几个原因,十进制数不足以用于科学应用:
+---------+----------------+---------+----------+---------------------------------------------+
| C# | .Net Framework | Signed? | Bytes | Possible Values |
| Type | (System) type | | Occupied | |
+---------+----------------+---------+----------+---------------------------------------------+
| sbyte | System.Sbyte | Yes | 1 | -128 to 127 |
| short | System.Int16 | Yes | 2 | -32768 to 32767 |
| int | System.Int32 | Yes | 4 | -2147483648 to 2147483647 |
| long | System.Int64 | Yes | 8 | -9223372036854775808 to 9223372036854775807 |
| byte | System.Byte | No | 1 | 0 to 255 |
| ushort | System.Uint16 | No | 2 | 0 to 65535 |
| uint | System.UInt32 | No | 4 | 0 to 4294967295 |
| ulong | System.Uint64 | No | 8 | 0 to 18446744073709551615 |
| float | System.Single | Yes | 4 | Approximately ±1.5 x 10-45 to ±3.4 x 1038 |
| | | | | with 7 significant figures |
| double | System.Double | Yes | 8 | Approximately ±5.0 x 10-324 to ±1.7 x 10308 |
| | | | | with 15 or 16 significant figures |
| decimal | System.Decimal | Yes | 12 | Approximately ±1.0 x 10-28 to ±7.9 x 1028 |
| | | | | with 28 or 29 significant figures |
| char | System.Char | N/A | 2 | Any Unicode character (16 bit) |
| bool | System.Boolean | N/A | 1 / 2 | true or false |
+---------+----------------+---------+----------+---------------------------------------------+
我不会重复在其他答案和评论中已经回答过的大量好(和坏)信息,但是我将向您提示一些后续问题:
有人什么时候会使用其中之一?
使用十进制计数值
将浮点/双精度用作测量值
一些例子:
钱(我们数钱还是衡量钱?)
距离(我们计算距离还是测量距离?*)
分数(我们计算分数还是衡量分数?)
我们总是数钱,永远不要衡量。我们通常测量距离。我们经常计算分数。
*在某些情况下,我称之为标称距离,我们可能确实想“计算”距离。例如,也许我们正在处理显示到城市距离的国家标志,并且我们知道这些距离永远不会超过一个十进制数字(xxx.x km)。
float
7位精度
double
大约有15位数字的精度
decimal
约有28位精度
如果需要更高的精度,请使用double而不是float。在现代CPU中,两种数据类型几乎都具有相同的性能。使用float的唯一好处是它们占用的空间更少。实际上只有在您有很多的情况下才重要。
我发现这很有趣。每位计算机科学家都应了解的浮点运算法则
double
在没有大于32位整数类型可用的情况下(并且基本上只在那些情况下),并且在double
使用时就好像它是53位整数类型(例如用于保留),我认为在会计应用程序中是合适的便士的总数,或百分之一的总数)。如今,此类语言用途不大,但是许多语言早在获得64位(甚至在某些情况下甚至是32位!)整数数学之前就已经能够使用双精度浮点值。
Real
IIRC可以以单位精度表示高达1.8E + 19的值。我认为,Real
比起…… ,会计应用程序要代表几分
double
单位精度高达9E15 的类型是非常普遍的。如果需要存储大于最大可用整数类型的整数,则使用数字double
比尝试进行多精度数学运算更容易,更有效,特别是考虑到处理器具有执行16x16-> 32 or的指令。 ..
没有人提到
在默认设置下,浮点数(System.Single)和双精度数(System.Double)将永远不会使用溢出检查,而十进制(System.Decimal)将始终使用溢出检查。
我的意思是
decimal myNumber = decimal.MaxValue;
myNumber += 1;
抛出OverflowException。
但是这些不:
float myNumber = float.MaxValue;
myNumber += 1;
和
double myNumber = double.MaxValue;
myNumber += 1;
float.MaxValue+1 == float.MaxValue
,就像decimal.MaxValue+0.1D == decimal.MaxValue
。也许您的意思是float.MaxValue*2
?
System.Decimal
抛出之前变得无法分辨整个单元的异常,但如果一个应用程序应该能够处理如美元和美分,这可能是太晚了。
decimal
除以零(CS0020)时,编译才会失败,并且整数文字也是如此。但是,如果运行时十进制值除以零,则会得到异常,而不是编译错误。
如前所述,整数是整数。他们无法存储点,例如.7,.42和.007。如果需要存储不是整数的数字,则需要另一种类型的变量。您可以使用double类型或float类型。您可以通过完全相同的方式设置这些类型的变量:您无需输入单词int
,而是输入double
或float
。像这样:
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#将再次向上或向下取整。道德是如果您想准确性,请注意四舍五入!
decimal
实际上是以十进制格式存储的(相对于基数2;因此不会由于两个数字系统之间的转换而丢失或舍入数字);此外,decimal
没有特殊值的概念,例如NaN,-0,∞或-∞。
对于我来说,这是一个有趣的话题,因为今天,我们遇到了一个讨厌的小错误,涉及到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(),输出值);//将返回0
奇怪的是,解决方案是double
先将Excel值转换为,然后转换为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
精度不如a decimal
,这实际上确保了仍然可以识别出少量数字。由于某种原因,double.TryParse
实际上能够检索到如此小的数字,而decimal.TryParse
会将它们设置为零。
奇。很奇怪。
decimal.Parse("0.00006317592")
有效-您还有其他事情要发生。-可能是科学记数法吗?
Decimal,Double和Float变量类型在存储值方面有所不同。精度是主要区别,其中float是单精度(32位)浮点数据类型,double是双精度(64位)浮点数据类型,而十进制是128位浮点数据类型。
浮点数-32位(7位数字)
双精度-64位(15-16位)
十进制-128位(28-29位有效数字)
有关... 的更多信息... 小数,浮点数和双精度之间的区别
所有这些类型的问题都是存在一定的不精确性,并且使用小十进制数可能会出现此问题,如以下示例所示
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,这是一个很好的答案。
双重地,问题在于fMean-fDelta = 1.09999999999,它低于1.1。
注意:我认为其他数字肯定会存在相同的问题,因为十进制只是精度较高的双精度数,精度始终有极限。
实际上,Double,Float和Decimal对应于COBOL中的BINARY十进制!
遗憾的是,.Net中不存在用COBOL实现的其他数字类型。对于不了解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)
简单来说:
/==========================================================================================
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。
Decimal
适合于金融应用程序,这是在Decimal
和之间确定的主要标准Double
。例如,很少有Double
精度不足以用于科学应用(并且由于其范围有限,Decimal
常常不适合科学应用)。
十进制 128位(28-29位有效数字)在金融应用程序中,最好使用十进制类型,因为它可以提供较高的准确性,并且易于避免舍入错误。对于需要精度的非整数数学,请使用十进制(例如货币和货币)
双 精度64位(15-16位数字)双精度类型可能是用于实值的最常用数据类型,除了处理资金外。对于不需要最精确答案的非整数数学,请使用double。
浮点 32位(7位数字),它主要用于图形库中,因为对处理能力的要求非常高,还使用了会承受舍入误差的情况。
Decimals
比慢得多double/float
。
Decimals
并且Floats/Doubles
不能没有投,而相比较Floats
,并Doubles
可以。
Decimals
还允许编码或尾随零。
您必须将值提及为:
Decimal dec = 12M/6;
Double dbl = 11D/6;
float fl = 15F/6;
并检查结果。
Float - 4
Double - 8
Decimal - 12