日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql float 精度阶段_mysql下float类型使用一些误差详解

發布時間:2025/3/19 数据库 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql float 精度阶段_mysql下float类型使用一些误差详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

單精度浮點數用4字節(32bit)表示浮點數

采用IEEE754標準的計算機浮點數,在內部是用二進制表示的

如:7.22用32位二進制是表示不下的。

所以就不精確了。

mysql中float數據類型的問題總結

對于單精度浮點數Float:? 當數據范圍在±131072(65536×2)以內的時候,float數據精度是正確的,但是超出這個范圍的數據就不穩定,沒有發現有相關的參數設置建議:將float改成double或者decimal,兩者的差別是double是浮點計算,decimal是定點計算,會得到更精確的數據。

1.float類型

float列類型默認長度查不到結果,必須指定精度,

比如 num? float,? insert into? table (num) values (0.12); select? * from table where num=0.12的話,empty set。

復制代碼代碼如下:

num float(9,7),? insert into? table (num) values (0.12); select? * from table where num=0.12的話會查到這條記錄。

mysql> create table tt

-> (

-> num? float(9,3)

-> );

Query OK, 0 rows affected (0.03 sec)

mysql> insert into tt(num)values(1234567.8);

ERROR 1264 (22003): Out of range value for column 'num' at row 1

注:超出字段范圍,無法插入

代碼如下 復制代碼

mysql> insert into tt(num)values(123456.8);

Query OK, 1 row affected (0.00 sec)

mysql> select? * from? tt;

+------------+

| num??????? |

+------------+

| 123456.797 |

+------------+

1 row in set (0.00 sec)

注:小數位數不夠,自動補齊,但是存在一個問題就是如上的近似值。

復制代碼代碼如下:

mysql> insert into tt(num)values(123456.867);

Query OK, 1 row affected (0.04 sec)

mysql> select * from?? tt;

+------------+

| num??????? |

+------------+

| 123456.797 |

| 123456.797 |

| 123456.867 |

+------------+

3 rows in set (0.00 sec)

mysql> select? * from tt where? num=123456.867;

+------------+

| num??????? |

+------------+

| 123456.867 |

+------------+

1 row in set (0.00 sec)

mysql> insert into tt(num)values(2.8);

Query OK, 1 row affected (0.04 sec)

mysql> select * from?? tt;

+------------+

| num??????? |

+------------+

| 123456.797 |

| 123456.797 |

| 123456.867 |

|????? 2.800 |

+------------+

4 rows in set (0.00 sec)

mysql> select? * from tt where? num=2.8;

+-------+

| num?? |

+-------+

| 2.800 |

+-------+

1 row in set (0.00 sec)

mysql> insert into tt(num)values(2.888888);

Query OK, 1 row affected (0.00 sec)

mysql> select? * from? tt;

+------------+

| num??????? |

+------------+

| 123456.797 |

| 123456.797 |

| 123456.867 |

|????? 2.800 |

|????? 2.889 |

+------------+

5 rows in set (0.00 sec)

注:小數位數超了,自動取近似值。

一、浮點數的概念及誤差問題

浮點數是用來表示實數的一種方法,它用 M(尾數) * B( 基數)的E(指數)次方來表示實數,相對于定點數來說,在長度一定的情況下,具有表示數據范圍大的特點。但同時也存在誤差問題,這就是著名的浮點數精度問題!浮點數有多種實現方法,計算機中浮點數的實現大都遵從 IEEE754 標準,IEEE754 規定了單精度浮點數和雙精度浮點數兩種規格,單精度浮點數用4字節(32bit)表示浮點數,格式是:1位符號位 8位表示指數 23位表示尾數??? 雙精度浮點數8字節(64bit)表示實數,格式是:1位符號位 11位表示指數 52位表示尾數??? 同時,IEEE754標準還對尾數的格式做了規范:d.dddddd...,小數點左面只有1位且不能為零,計算機內部是二進制,因此,尾數小數點左面部分總是1。顯然,這個1可以省去,以提高尾數的精度。由上可知,單精度浮點數的尾數是用24bit表示的,雙精度浮點數的尾數是用53bit表示的,轉換成十進制:

2^24 - 1 = 16777215;? 2^53 - 1 = 9007199254740991

由上可見,IEEE754單精度浮點數的有效數字二進制是24位,按十進制來說,是8位;雙精度浮點數的有效數字二進制是53位,按十進制來說,是16 位。顯然,如果一個實數的有效數字超過8位,用單精度浮點數來表示的話,就會產生誤差!同樣,如果一個實數的有效數字超過16位,用雙精度浮點數來表示,也會產生誤差!對于 1310720000000000000000.66 這個數,有效數字是24位,用單精度或雙精度浮點數表示都會產生誤差,只是程度不同:

單精度浮點數:1310720040000000000000.00;雙精度浮點數: 1310720000000000000000.00

可見,雙精度差了 0.66 ,單精度差了近4萬億!

以上說明了因長度限制而造成的誤差,但這還不是全部!采用IEEE754標準的計算機浮點數,在內部是用二進制表示的,但在將一個十進制數轉換為二進制浮點數時,也會造成誤差,原因是不是所有的數都能轉換成有限長度的二進制數。對于131072.32 這個數,其有效數字是8位,按理應該能用單精度浮點數準確表示,為什么會出現偏差呢?看一下這個數據二進制尾數就明白了 10000000000000000001010001......???? 顯然,其尾數超過了24bit,根據舍入規則,尾數只取 100000000000000000010100,結果就造成測試中遇到的“奇怪”現象!131072.68 用單精度浮點數表示變成 131072.69 ,原因與此類似。實際上有效數字小于8位的數,浮點數也不一定能精確表示,7.22這個數的尾數就無法用24bit二進制表示,當然在數據庫中測試不會有問題(舍入以后還是7.22),但如果參與一些計算,誤差積累后,就可能產生較大的偏差。

二、mysql 和 oracle中的數值類型

問題是不是只有 mysql 存在呢?顯然不是,只要是符合IEEE754標準的浮點數實現,都存在相同的問題。

mysql中的數值類型(不包括整型):

IEEE754浮點數:float(單精度),double或real(雙精度)

定點數:decimal或numeric

oracle中的數值類型:

oracle 浮點數 :number(注意不指定精度)

IEEE754浮點數:BINARY_FLOAT(單精度),BINARY_DOUBLE(雙精度)FLOAT,FLOAT(n) (ansi要求的數據類型)

定點數:number(p,s)

如果在oracle中,用BINARY_FLOAT等來做測試,結果是一樣的。因此,在數據庫中,對于涉及貨幣或其他精度敏感的數據,應使用定點數來存儲,對mysql來說是 decimal,對oracle來說就是number(p,s)。雙精度浮點數,對于比較大的數據同樣存在問題!

三、編程中也存在浮點數問題

不光數據庫中存在浮點數問題,編程中也同樣存在,甚至可以說更值得引起注意!

通過上面的介紹,浮點數的誤差問題應該比較清楚了。如果在程序中做復雜的浮點數運算,誤差還會進一步放大。因此,在程序設計中,如果用到浮點數,一定要意識到可能產生的誤差問題。不僅如此,浮點數如果處理不好,還會導致程序BUG!看下面的語句:if (x != y) { z = 1 / (x -y);}這個語句看起來沒有問題,但如果是浮點數,就可能存在問題!再看下面的語句會輸出什么結果: public class Test { public static void main(String[]args) throws Exception { System.out.print("7.22-7.0=" + (7.22f-7.0f)); } }???? 我們可能會想當然地認為輸出結果應該是 0.22 ,實際結果卻是 0.21999979 !

因此,在編程中應盡量避免做浮點數的比較,否則可能會導致一些潛在的問題!除了這些,還應注意浮點數中的一些特殊值,如 NaN、+0、-0、+無窮、-無窮等,IEEE754雖然對此做了一些約定,但各具體實現、不同的硬件結構,也會有一些差異,如果不注意也會造成錯誤!

四、總結:

從上面的分析,我們可以得出以下結論:

1、浮點數存在誤差問題;

2、對貨幣等對精度敏感的數據,應該用定點數表示或存儲;

3、編程中,如果用到浮點數,要特別注意誤差問題,并盡量避免做浮點數比較;

4、要注意浮點數中一些特殊值的處理

注意事項

MYSQL 5.022中,

如果某個字段 f是float類型,那么在查詢的時候,sql語句為:

select * from T where f = 2.2;

那么即使表中有2.2的數據也不能被查詢到.

此時解決方法有2種:

1.將float改為double類型,不會出現這種問題.但是如果數據庫中數據量龐大,或者修改量太大,則不適合這個方法.這個方法只適合設計數據庫的初期階段.

2.設置float的精度然后進行查詢就可以了.

如果要精確到3位,則:select * from T where format(f,3) = format(2.2,3);

但是,精度不能超過6.否則出錯.因為float類型最多允許精確到小數點后6位.

總結

以上是生活随笔為你收集整理的mysql float 精度阶段_mysql下float类型使用一些误差详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。