天天看點

.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的唯一好處是它們占用的空間更少。 實際上隻有在您有很多的情況下才重要。

我發現這很有趣。 每個計算機科學家都應了解的浮點運算法則

繼續閱讀