2008-12-01 24 views
11

我在Oracles documentation看到衝突引用。數據庫中FLOAT和NUMBER類型的小數點之間存在什麼區別?Oracle浮動與數字

正如我從C等人記得的那樣,float具有int不具有的精度限制。例如,對於'float',0.1(基數10)近似爲0.110011001100110011001101(基數2),其基本上等於0.100000001490116119384765625(基數10)。但是,對於'int',5(基數10)恰好是101(基數2)。

這就是爲什麼如預期在C以下不會終止:

float i; 
i = 0; 
for (i=0; i != 10;) 
{ 
    i += 0.1 
} 

但是我看到漂浮已被定義爲一個NUMBER elsewhere in Oracle's documentation。據我所知,Oracle的NUMBER類型的實現不會遇到與C的float類似的問題。

那麼,這裏真正的故事是什麼?甲骨文是否偏離了我期望與浮動/ FLOAT發生的規範? (我敢肯定,這是一個我將使用它們的蜜蜂放屁的差異,但是我知道如果0.1 * 10出現在1.00000000000000001之後我會有問題)

回答

22

甲骨文BINARY_FLOAT商店內部使用IEEE 754浮點表示,像C和許多其他語言的數據做。當您從數據庫中獲取數據時,通常以主機語言的形式將數據存儲在IEEE 754數據類型中,這樣就可以複製數據而不用進行轉換。

儘管Oracle的FLOAT數據類型是ANSI SQL NUMERIC數據類型的同義詞,在Oracle中稱爲NUMBER。這是一個精確的數字,是一種不具有IEEE 754四捨五入行爲的縮放十進制數據類型。但是,如果從數據庫中提取這些值並將它們放入C或Java浮點數,則在此步驟中可能會失去精度。

3

Oracle's Number實際上是一個十進制(基數爲10)的浮點表示... Float只是Number的別名,並且完全一樣。

如果你想要二進制(base-2)浮點數,你需要使用Oracle的BINARY_FLOAT或BINARY_DOUBLE數據類型。

link text

10

Oracle BINARY_FLOAT和BINARY_DOUBLE大部分等同於IEEE 754標準,但它們絕對不是內部存儲在標準IEEE 754表示中。

例如,一個BINARY_DOUBLE需要9個字節的存儲量,而IEEE的8個。同樣,雙浮點數-3.0表示爲3F-F7-FF-FF-FF-FF-FF-FF,如果使用真正的IEEE將是C0-08-00-00-00-00-00-00。請注意,Oracle表示中的第63位爲0,而IEEE第1位爲1(如果's'是符號位,根據IEEE,數字的符號爲(-1)^ s)。看到很好的IEEE 754計算器在http://babbage.cs.qc.cuny.edu/IEEE-754/

你可以很容易地找到這個,如果你有表T一BINARY__DOUBLE列BD與查詢:

選擇BD,在T

DUMP(BD)

現在,所有這一切都是好的和有趣的(可能),但是當在C中工作並從Oracle獲取數值(通過將變量綁定到任何類型的數字列)時,通常會得到真實IEEE現在這個值受到所有通常的IEEE不準確性的限制。

如果你想要做精確的算術,可以用PL/SQL或者使用特殊的精確算術C庫來完成。

對於Oracle自己的數字數據類型的說明,請參見:http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/datatype.htm#i16209

2

比爾的有關Oracle FLOAT答案是唯一正確的後期版本(比如11i的),在Oracle 8i中,該文件說:

您可以使用 「NUMBER Datatype」中討論的形式指定浮點數。 Oracle還支持ANSI數據類型FLOAT。你 可以指定使用的這些句法形式之一此數據類型:

FLOAT指定與小數精度38,或二進制 精度浮點數126 FLOAT(b)中指定與 二進制精度B A浮點數。精度b的範圍可以從1到126.要將 從二進制轉換爲十進制精度,請將b乘以0.30103。若要將 從十進制轉換爲二進制精度,請將小數點 精度乘以3.32193。二進制精度的最大126位數爲 ,大致相當於38位十進制精度。

它聽起來像一個四倍精度(126二進制精度)。如果我沒有弄錯,IEEE754只需要b = 2,單精度p = 24,雙精度p = 53。當我在研究Oracle和PostgreSQL之間的轉換計劃時,8i和11i之間的差異導致了很多混淆。

2

像前面提到的,BINARY_FLOAT和BINARY_DOUBLE類型Oracle 10g中使用機器算術PLS_INTEGER並且需要較少的存儲空間,這兩者使它們比NUMBER類型

  • ONLY BINARY_FLOAT和BINARY_DOUBLE支持NAN更高效值

- 沒有精確的計算