天天看点

.NET中小数,浮点数和双精度之间的区别?

.NET中的

decimal

float

double

float

什么区别?

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

#1楼

对我来说,这是一个有趣的话题,因为今天,我们遇到了一个讨厌的小错误,涉及到

decimal

float

精度低。

在我们的C#代码中,我们正在从Excel电子表格中读取数值,将其转换为

decimal

,然后将该

decimal

发送回Service以保存到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

奇怪的是,解决方案是先将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

会将它们设置为零。

奇。 很奇怪。

#2楼

如前所述,整数是整数。 他们无法存储点,例如.7,.42和.007。 如果需要存储不是整数的数字,则需要另一种类型的变量。 您可以使用double类型或float类型。 您可以以完全相同的方式设置这些类型的变量:键入

double

float

而不是使用

int

字。 像这样:

float myFloat;
double myDouble;
           

float

是“ floating point”的缩写,仅表示末尾带有数字的数字。)

两者之间的区别在于它们可以容纳的数字的大小。 对于

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#将再次向上或向下取整。 道德是如果您想准确性,请注意四舍五入!

#3楼

+---------+----------------+---------+----------+---------------------------------------------+
| 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/Forums/zh-CN/csharpgeneral/thread/921a8ffc-9829-4145-bdc9-a96c1ec174a5

#4楼

  • 浮点数:±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有效数字)

#5楼

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

#6楼

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

浮点数-32位(7位数字)

双精度-64位(15-16位)

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

有关... 的更多信息... 小数,浮点数和双精度之间的区别

#7楼

这些之间的主要区别在于精度。

float

32-bit

数字,

double

64-bit

数字,

decimal

128-bit

数字。

#8楼

没有人提到

在默认设置中,浮点数(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;
           

#9楼

  1. Double和float可以被整数零除,在编译和运行时均无例外。
  2. 小数不能除以整数零。 如果这样做,编译将始终失败。

#10楼

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

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

将十进制用作计数值

将浮点/双精度用作测量值

一些例子:

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

我们总是数钱,永远不要衡量。 我们通常测量距离。 我们经常计算分数。

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

#11楼

所有这些类型的问题是存在一定的不精确性,并且使用小十进制数可能会出现此问题,如以下示例所示

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。

注意:我认为其他数字肯定存在相同的问题,因为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) 
           

#12楼

简单来说:

  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 。

#13楼

十进制结构严格适合需要准确性的财务计算,而这些准确性相对不能四舍五入。 但是,由于以下几个原因,十进制数不足以用于科学应用:

  • 由于许多物理问题或被测量工件的实际限制,在许多科学计算中,一定程度的精度损失是可以接受的。 精度损失在金融中是不可接受的。
  • 对于大多数操作,小数比浮点和双精度慢很多(很多),主要是因为浮点运算是在二进制中完成的,而小数填充是在基数10中完成的(即浮点和双精度是由FPU硬件(例如MMX / SSE)处理的,而小数则由软件计算得出)。
  • 尽管十进制支持更多位数的精度,但其取值范围小于双精度数,这是不可接受的。 因此,十进制不能用来表示许多科学价值。

#14楼

精度是主要区别。

浮点数 -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
           

#15楼

float

double

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

10001.10010110011
           

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

decimal

是一种浮动的小数点类型 。 换句话说,它们代表这样的数字:

12345.65789
           

同样, 小数点的数字和位置都在值中进行编码-这就是使

decimal

仍然是浮点类型而不是定点类型的原因。

需要注意的重要一点是,人类习惯于以十进制形式表示非整数,并期望以十进制表示形式得到准确的结果。 并非所有十进制数字都可以在二进制浮点数中精确表示(例如0.1),因此,如果您使用二进制浮点数,则实际上将近似为0.1。 当使用浮点小数点时,您仍然会得到近似值-例如,不能精确表示1除以3的结果。

至于什么时候使用:

  • 对于“自然精确的小数”值,最好使用

    decimal

    。 这通常适用于人类发明的任何概念:财务价值是最明显的例子,但也有其他一些例子。 例如,考虑给潜水员或溜冰者的分数。
  • 对于更多自然伪造的值,无论如何也无法真正准确地测量它们,则使用

    float

    /

    double

    更为合适。 例如,科学数据通常以这种形式表示。 在这里,原始值一开始就不会是“十进制精度”,因此对于预期结果而言,保持“十进制精度”并不重要。 浮点二进制点类型比十进制小得多。

#16楼

float

7位精度

double

的精度约为15位

decimal

的精度约为28位

如果需要更高的精度,请使用double而不是float。 在现代CPU中,两种数据类型几乎都具有相同的性能。 使用float的唯一好处是它们占用的空间更少。 实际上只有在您有很多的情况下才重要。

我发现这很有趣。 每个计算机科学家都应了解的浮点运算法则