.NET 中小数、浮点和双精度之间的区别?
-
03-07-2019 - |
题
有什么区别 decimal
, float
和 double
在.NET 中?
什么时候有人会使用其中之一?
解决方案
float
和 double
是 漂浮的 二进制 点类型. 。换句话说,它们代表这样的数字:
10001.10010110011
二进制数和二进制小数点的位置都编码在该值内。
decimal
是一个 漂浮的 小数 点型. 。换句话说,它们代表这样的数字:
12345.65789
再次,数量和位置 小数 点都被编码在值中——这就是为什么 decimal
仍然是浮点类型而不是定点类型。
需要注意的重要一点是,人类习惯于以十进制形式表示非整数,并期望以十进制表示形式得到精确的结果;并非所有十进制数都可以精确地用二进制浮点表示 - 例如 0.1 - 因此,如果您使用二进制浮点值,您实际上会得到 0.1 的近似值。使用浮动小数点时,您仍然会得到近似值 - 例如,无法精确表示 1 除以 3 的结果。
至于什么时候用什么:
对于“自然精确的小数”的值,最好使用
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
Decimal 结构严格适合需要精确度的金融计算,相对不能容忍舍入。然而,小数不足以满足科学应用的需要,原因如下:
- 由于所测量的物理问题或工件的实际限制,在许多科学计算中一定程度的精度损失是可以接受的。在金融领域,精度损失是不可接受的。
- 对于大多数运算来说,Decimal 比 float 和 double 慢得多,主要是因为浮点运算是以二进制完成的,而 Decimal 的东西是以 10 为基数完成的(即,以 10 为基数)。浮点数和双精度数由 FPU 硬件处理,例如 MMX/SSE,而小数则在软件中计算。
- 尽管 Decimal 支持更多位数的精度,但它的值范围比 double 小得令人无法接受。因此,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 |
+---------+----------------+---------+----------+---------------------------------------------+
有关详细信息,请参阅:
http://social.msdn .microsoft.com /论坛/ EN-US / csharpgeneral /线程/ 921a8ffc-9829-4145-bdc9-a96c1ec174a5
float
7位精度
double
大约有15位精度
decimal
具有大约28位精度
如果您需要更高的准确度,请使用double而不是float。 在现代CPU中,两种数据类型具有几乎相同的性能。使用浮动的唯一好处是它们占用的空间更少。只有当你有很多这样的时候才真正重要。
我发现这很有趣。 每个计算机科学家应该知道的关于浮点算术的内容一>
我不会重申其他答案和评论中已经回答的大量好(和一些坏)信息,但我将通过提示回答您的后续问题:
什么时候有人会使用其中之一?
使用小数表示 数过的 价值观
使用 float/double 进行 测量的 价值观
一些例子:
钱(我们数钱还是衡量钱?)
距离(我们计算距离还是测量距离?*)
分数(我们计算分数还是衡量分数?)
我们总是数钱而不应该衡量它。我们通常测量距离。我们经常计算分数。
* 在某些情况下,我会称之为 标称距离, ,我们可能确实想“计算”距离。例如,也许我们正在处理显示到城市距离的国家/地区标志,并且我们知道这些距离永远不会超过一位小数位(xxx.x 公里)。
没人提到
在默认设置中,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;
如上所述,整数是整数。他们无法存储点数,例如.7,.42和.007。如果您需要存储非整数的数字,则需要使用不同类型的变量。您可以使用double类型或float类型。您以完全相同的方式设置这些类型的变量:而不是使用单词 int
,键入 double
或 float
。像这样:
float myFloat;
double myDouble;
( float
是“浮点数”的缩写,只是表示最后有一个点的数字。)
两者之间的差异在于它们可以容纳的数字的大小。对于 float
,您的号码最多可包含7位数字。对于 double
,最多可包含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#将再次向上或向下舍入。道德是如果你想要准确,小心四舍五入!
- Double和float可以除以整数零,在编译和运行时都没有异常。
- 十进制不能除以整数零。如果你这样做,编译总是会失败。 醇>
这对我来说是一个有趣的话题,因为今天,我们刚刚遇到了一个令人讨厌的小错误,涉及 decimal
精度低于 float
.
在我们的 C# 代码中,我们从 Excel 电子表格中读取数值,并将其转换为 decimal
, ,然后发送这个 decimal
返回到服务以保存到 SQL服务器 数据库。
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.00006317592
Decimal.TryParse(cellValue.ToString(), 输出值); // 会返回 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
会将它们设置为零。
奇怪的。很奇怪。
- 漂浮:±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 位有效数字)
对于内存和性能都很关键的游戏和嵌入式系统等应用程序,float通常是数字类型,因为它更快,是double的一半大小。整数曾经是首选武器,但浮点性能在现代处理器中已超过整数。十进制就出来了!
Decimal,Double和Float变量类型在存储值方面有所不同。精度是主要区别,其中float是单精度(32位)浮点数据类型,double是双精度(64位)浮点数据类型,decimal是128位浮点数据类型。
Float - 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 !!!
如果我用Decimal替换Double,则bLower包含FALSE,这是一个很好的答案。
在double中,问题是fMean-fDelta = 1.09999999999低于1.1。
警告:我认为其他数字肯定存在同样的问题,因为Decimal只是一个精度更高的双精度,并且精度总是有限制。
实际上,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)
简单来说:
- Decimal,Double和Float变量类型在存储值方面有所不同。
- 精度是 主要差异 (请注意,这不是单一的差异) float 是单精度(32位)浮动点数据类型, double 是双精度(64位)浮点数据类型,十进制是128位浮点数据类型。
- 摘要表: 醇>
/==========================================================================================
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 ,十进制。
每种方法之间的主要区别在于精度。
float
是 32位
号, double
是 64位
号和 decimal
是 128位
号。