.NET中decimal,float和double的区别?
.NET中的decimal
, float
和double
什么区别?
什么时候有人使用其中之一?
float
和double
是浮点二进制types 。 换句话说,他们代表了这样一个数字:
10001.10010110011
二进制数字和二进制点的位置都编码在该值内。
decimal
是一个浮点小数点types 。 换句话说,他们代表了这样一个数字:
12345.65789
同样, 小数点的位置和数字都被编码在这个值中 – 这就是decimal
仍然是一个浮点types,而不是一个固定点types。
重要的是要注意的是,人类习惯于以十进制forms表示非整数,并期望在十进制表示中得到确切的结果。 并不是所有的十进制数都可以在二进制浮点数中精确表示 – 例如0.1 – 所以如果使用二进制浮点数值,则实际上会得到0.1的近似值。 例如,当使用浮动小数点时,仍然会得到近似值 – 例如,除以1得到的结果不能被精确地表示。
至于什么时候使用:
-
对于“自然精确小数”的值,可以使用小数。 这通常适用于人类发明的任何概念:财务价值是最明显的例子,但也有其他的例子。 例如,考虑给予潜水员或溜冰者的分数。
-
对于自然界更多的文物来说,无论如何都无法准确衡量,
float
/double
更合适。 例如,科学数据通常会以这种forms表示。 在这里,原始值不会以“小数精度”开始,所以对于预期的结果来说,保持“小数精度”并不重要。 浮点二进制types的处理比小数快得多。
精度是主要的区别。
浮点数 – 7位数(32位)
双 15-16位(64位)
十进制 -28-29有效数字(128位)
小数具有更高的精度,通常用于需要高度准确性的金融应用中。 小数点比双/浮点数慢得多(在一些testing中高达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慢得多(主要是因为浮点运算是以二进制forms完成的,而Decimal是在10进制的)(即浮点和双精度由FPU硬件处理,如MMX / SSE ,而小数则用软件计算)。
- 尽pipe支持更多数字的精度,但十进制的值范围比双精度值小得无法接受。 因此,十进制不能用来代表许多科学价值。
欲了解更多信息,你可以去这张照片的来源:
float
7位精度
double
精度约为15位
decimal
有大约28个数字的精度
如果你需要更好的精度,使用double而不是float。 在现代CPU中,两种数据types的性能几乎相同。 使用浮动的唯一好处是占用更less的空间。 实际上只有当你有很多这样的事情时才重要。
我发现这很有趣。 计算机科学家应该知道什么是浮点运算
没有人提到过
在默认设置中,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;
- 在编译和运行时,double和float都可以被整数零除。
- 十进制不能被整数零除。 如果你这样做,编译将会失败。
Decimal,Double和Floatvariablestypes的存储方式不同。 float是单精度(32位)浮点数据types的精度,double是双精度(64位)浮点数据types,decimal是128位浮点数据types。
浮点数 – 32位(7位数字)
双64位(15-16位)
十进制 – 128位(28-29位有效数字)
主要区别是Floats和Doubles是二进制浮点types,Decimal会将该值存储为浮点小数点types。 所以小数的精度要高得多,通常用在要求高精度的货币(金融)或科学计算应用中。 但在性能方面,小数比双精度和浮点types慢。
十进制可以100%精确地表示小数格式精度内的任何数字,而“浮点数”和“双精度数”不能精确地表示所有数字,即使是在各自格式精度范围内的偶数。
十进制
在财务应用或科学计算的情况下,最好使用十进制types,因为它为您提供了高级别的准确性,并且容易避免舍入错误
双
除了处理金钱之外,双重types可能是实际值最常用的数据types。
浮动
它主要用于graphics库,因为对处理能力的要求非常高,也使用了可以忍受舍入误差的情况。
我不会重复在其他答案和评论中已经回答的很多好的(和一些坏的)信息,但是我会用一个提示来回答你的后续问题:
什么时候有人使用其中之一?
计数值使用小数
使用float / double作为测量值
一些例子:
-
钱(我们数钱还是数钱?)
-
距离(我们计算距离还是测量距离?*)
-
分数(我们计数分数还是分数?)
我们总是数钱,不应该衡量它。 我们通常测量距离。 我们经常计数分数。
*在某些情况下,我称之为标称距离 ,我们可能确实要'算'距离。 例如,也许我们正在处理显示与城市距离的国家标志,而且我们知道这些距离从来没有超过一个十进制数字(xxx.x km)。
如前所述,整数是整数。 他们不能存储点,如.7,.42和.007。 如果您需要存储不是整数的数字,则需要使用不同types的variables。 您可以使用双精度型或浮点型。 你用完全相同的方式设置这些types的variables:而不是使用int这个词,你inputdouble或float。 喜欢这个:
float myFloat; double myDouble;
(浮点数是“浮点数”的缩写,只是意味着一个数字,并且有点数。
两者之间的区别在于它们可以容纳的数字的大小。 对于浮点数,您的号码最多可以有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位的数字。
双击你的新button来获得代码。 将以下三行添加到您的button代码中:
double myDouble; myDouble = 0.007; MessageBox.Show(myDouble.ToString());
暂停你的程序并返回到编码窗口。 改变这一行:
myDouble = 0.007; myDouble = 12345678.1234567;
运行你的程序,然后点击双击button。 消息框正确显示数字。 尽pipe如此,最后再添加一个数字,而C#会再次向上或向下舍入。 道德是,如果你想准确,谨慎四舍五入!
这一直是我的一个有趣的线索,就像今天,我们刚刚有一个讨厌的小错误,关于“十进制”精度比“浮动”less。
在我们的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 value); 会返回0
奇怪的解决scheme是将Excel的值先转换成double ,再转换成小数 。
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; ... }
尽pipedouble的精确度小于小数 ,但这实际上确保了小数字仍然可以被识别。 出于某种原因,“ double.TryParse ”实际上能够检索这样的小数字,而“ decimal.TryParse ”会将它们设置为零。
奇。 很奇怪。
浮动〜±1.5×10-45至±3.4×1038 ——– 7个数字
双±5.0 x 10-324至±1.7 x 10308 —— 15或16位数字
十进制〜±1.0×10-28〜±7.9×1028 ——– 28或29个数字
对于内存和性能都很关键的游戏和embedded式系统等应用来说,float通常是数字types的select,因为它更快,是double的一半。 整数曾经是select的武器,但浮点性能在现代处理器中已经超过了整数。 十进制是正确的!
Decimal,Double和Floatvariablestypes的存储方式不同。 float是单精度(32位)浮点数据types的精度,double是双精度(64位)浮点数据types,decimal是128位浮点数据types。
浮点数 – 32位(7位数字)
双64位(15-16位)
十进制 – 128位(28-29位有效数字)
更多关于… Decimal,Float和Double的区别
所有这些types的问题是存在一定的不精确性并且这个问题可能发生在十进制小数上,就像下面的例子
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
问题:bLowervariables包含哪个值?
答:在32位机器上,bLower包含TRUE!
如果我用小数取代Double,bLower包含FALSE,这是很好的答案。
双倍,问题是fMean-fDelta = 1.09999999999比1.1低。
警告:我认为同样的问题可以肯定存在其他数字,因为十进制只有一个更高的精度和精度总是有限的一倍。
实际上,Double,Float和Decimal对应于COBOL中的BINARY小数点!
遗憾的是,在.Net中不存在COBOL中实现的其他数字types。 对于那些不了解COBOL的人来说,COBOL中存在以下数字types
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)
这两者之间的主要区别在于精度。
float
是32-bit
数字, double
是64-bit
数字, decimal
是128-bit
数字。