亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Double類型精度問題引起的錯誤

發布時間:2020-08-10 21:04:27 來源:ITPUB博客 閱讀:344 作者:jx_yu 欄目:MySQL數據庫

場景說明

研發同事讓把某個double類型字段的值四舍五入保留2位小數,mysqlround(col,2)可以實現四舍五入并且保留2位小數,但是神奇的事情發生了:發現有的四舍五入是正確的,而有的不是我們想要的結果,如下:簡單模擬此場景:

yujx>drop table dd;
yujx>
create table dd (a double);
yujx>
insert into dd values(956.745),(231.34243252),(321.43534),(5464.446);
yujx>
select a,round(a,2) from dd;
+--------------+------------+
| a            | round(a,2) |
+--------------+------------+
|     
956.745 |     956.74 |    #可以看到并不是我們期望的956.75
| 231.34243252 |     231.34 |
|    321.43534 |     321.44 |
|     5464.446 |    5464.45 |
+--------------+------------+
4 rows in set (0.00 sec)

如上,有的是正確的,有的不是我們期望的值,那么問題來了,為什么呢?

通過詢問和網上搜索后,發現可能是因為double的精度問題導致的

查閱MySQL官當關于doubleFloatDECIMAL, NUMERIC類型的介紹,如下:

FLOAT, DOUBLE

#為了說明問題,摘了官當的部分內容,關于更詳細的介紹請直接查看官當。

12.2.3 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE

#可以看到標題已經指出 Floatdouble是近似值

The FLOAT and DOUBLE types represent approximate numeric data values. MySQL uses four bytes for single-precision values and eight bytes for double-precision values.

 

Because floating-point values are approximate and not stored as exact values, attempts to treat them as exact in comparisons may lead to problems. They are also subject to platform or implementation dependencies. For more information, seeSection B.5.5.8, “Problems with Floating-Point Values

因為FloatDouble存儲的是一個近似值而不是確切的值,試圖使用它們存儲一個確切的值可以會導致問題。它們依賴于不同平臺和不同實現方式,而官當在章節Section B.5.5.8, “Problems with Floating-Point Values中舉例說明了此問題

參考:http://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html

“Problems with Floating-Point Values”

B.5.4.8 Problems with Floating-Point Values

Floating-point numbers sometimes cause confusion because they are approximate and not stored as exact values. A floating-point value as written in an SQL statement may not be the same as the value represented internally. Attempts to treat floating-point values as exact in comparisons may lead to problems. They are also subject to platform or implementation dependencies. The FLOAT and DOUBLE data types are subject to these issues. For DECIMALcolumns, MySQL performs operations with a precision of 65 decimal digits, which should solve most common inaccuracy problems.

由于浮點數存儲的是近似值而不是確切的值,某些時候可能導致混亂。一個浮點數值在SQL語句作為內部表示的值可能不同。試圖使用floatdouble來存儲確切的值可能會出現問題,他們也依賴不同平臺和實現方式。而對應DECIMAL類型,MySQL作為65位精度進行操作,可以解決此類精度問題。

如下例子證明使用Double運算遇到的異常錯誤

Double類型精度問題引起的錯誤

此結果是錯誤的,盡管前5條的ab的值看起來是不滿足a<>b條件的。

Double類型精度問題引起的錯誤

此現象取決于各種因素,如計算機架構、編譯器版本或者優化級別等。例如,不同的CPU評估的浮點數不同。

 

如果將字段d1d2改成DECIMAL類型,將不會存在此問題。如下:

Double類型精度問題引起的錯誤

綜上,如果想精確的存儲浮點數值,應該使用DECIMAL.比如金額等。

DECIMAL, NUMERIC

11.2.2 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC

The DECIMAL and NUMERIC types store exact numeric data values. These types are used when it

is important to preserve exact precision, for example with monetary data. In MySQL, NUMERIC is

implemented as DECIMAL

DECIMALNUMBERIC存儲的是確切的數值,使用它們可以保證精確度,例如用于存儲金額數據。在MySQL,NUMBERICDECIMAL以同樣的類型實現。

double在其他平臺

double類型不只是在MySQL中存在精度錯誤的問題,在oracleJava等平臺同樣存在此問題,如下:

Double類型精度問題引起的錯誤

簡單的0.2+0.4,但是返回的結果不是0.6

回到問題開始

如果換成DECIMAL類型,round的結果將是正確的,如下:

yujx>drop table dd;
yujx>
create table dd (a double,b decimal(30,10));
yujx>
insert into dd

values(956.745,956.745),(231.34243252,231.34243252),(321.43534,321.43534),

(5464.446,5464.446);
yujx>
select a,round(a,2) from dd;

Double類型精度問題引起的錯誤

 

綜上

只為說明一個問題,如果想要確切的存儲小數(例如,金額等),建議使用DECIMAL類型,而不是DOUBLEfloat類型。

 

參考:

http://dev.mysql.com/doc/refman/5.7/en/fixed-point-types.html

http://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html

http://dev.mysql.com/doc/refman/5.7/en/problems-with-float.html

http://justjavac.com/codepuzzle/2012/11/11/codepuzzle-float-who-stole-your-accuracy.html

 

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

建宁县| 襄垣县| 尼木县| 体育| 察隅县| 汕头市| 准格尔旗| 正宁县| 如东县| 苗栗市| 明光市| 沙雅县| 东乌珠穆沁旗| 山丹县| 磐安县| 谢通门县| 万荣县| 新竹县| 宣武区| 平山县| 邢台县| 延川县| 丹棱县| 神农架林区| 南部县| 巴东县| 乌兰察布市| 太湖县| 岳普湖县| 龙川县| 浑源县| 若羌县| 溆浦县| 图片| 博罗县| 邢台市| 从江县| 新河县| 天台县| 仁怀市| 黄龙县|