大數據

ODPS double類型轉型精度問題總結

從相差0.0000000000001說起,本文主要是對odps的Double和Decimal的精度使用問題做一個總結。

1. 問題描述

客戶開發人員在使用maxcompute對double數據類型求和時出現錯誤(數據表由oracle數據庫抽取到maxcompute, 對應字段類型為number到double),正確的結果是1943.38,但求和結果為1943.3799999999999,結果相差了0.0000000000001,這個差值的比例可以這樣類比——如果地球的周長(40076.02千米)作為單位1的話,那麼誤差換算出來是4微米,差不多是一個紅細胞的大小。絕大多數的情況下,我們可以忽略這個問題,但是在金融線,“差一微米也不行”。

2. 問題的根因:double求和帶來精度問題

double適合做科學計算,如果用來進行精確計算,會帶來精度丟失的問題。二進制的浮點數計算標準是IEEE二進制浮點數算術標準(ANSI/IEEE Std 754-1985),IEEE 754規定了四種表示浮點數值的方式:單精確度(32位)、雙精確度(64位)、延伸單精確度(43比特以上,很少使用)與延伸雙精確度(79比特以上,通常以80位實現),double類型通常指“雙精確度(64位)”,53位有效數字。要理解double的精度問題,我們從最基礎的二機制與十進制轉換看起,比如:如何用二進制表示0.1?小數是用整數除法來表示的,0.1=1/10(十進制)=1/1010(二進制),會得到一個除不盡的值,用double類型來表示這個數的時候就必須要進行截斷(舍入),得到的結果是0.00011001100110011001100110011001100110011001100110011010,如果把結果轉回十進制,會發現這個值已經不是0.1,精度問題產生了。同理,double類型在進行計算也會造成同樣的精度問題。

3. 如何解決——double轉型decimal

double計算會有精度問題,為了得到精確的結果,就要在計算之前進行處理,轉換成無損計算的類型之後,再進行計算,maxcompute提供了這種無損類型——decimal。

3.1 double直接轉成decimal再次遇到問題

不幸的是,直接轉型會遇到以下兩個問題:
1)轉型也會有精度損失。
2)同列的某些值看起來沒有精度損失,另一些有,出現表現不一致的情況。

image.png

  • double直接轉decimal會帶來精度損失,因為double的小數位有效位比decimal要少,decimal會對最後的幾位進行隨機數補齊,引入了精度問題。
  • 同列中某些值沒有出現任何精度損失,因為客戶使用了2.0數據類型版本,在這個版本中maxcompute對轉換進行了優化,對位數較小的數(測試結果為7位,供參考)採用了不同的轉型算法(類似decimal的處理方法,轉換成整數進行計算,保證無損)。位數較大的數無法採用該算法,標準算法處理,會出現精度損失。

4. 轉換成decimal就大功告成了麼?

4.1 incompatible type exception

decimal類型的計算雖然是無損的,但是decimal在計算過程可能會產生精度位數的變化,導致下圖中的問題:計算結果插入結果表中時出現"incompatible type"的錯誤。

image.png

4.2 如何避免

問題出現的原因是混用了1.0 decimal類型和2.0 decimal類型。若想有效的避免decimal計算導致的問題,需要遵循:

  • 從建表開始,始終使用同一種數據類型,不要混用。
  • 使用2.0數據類型,建源表和結果表時指定具體的decimal精度位,如decimal(35,6),避免計算中精度位數的變化。

5. 避免轉型問題的最佳實踐

如果希望避免精度問題,並且在計算過程中避免結果轉型,那麼可以將所有涉及精確計算的字段在建表時就採用2.0數據類型,並且指定所需要的精度,例如:

set odps.sql.decimal.odps2=true;
CREATE TABLE `ods_test` (
  ` account_balance` DECIMAL(38, 18) COMMENT '賬戶餘額'
)

在後續的查詢和計算過程中,設置“odps.sql.decimal.odps2=true”後進行操作,例如:

set odps.sql.decimal.odps2=true;
select sum(account_balance) from ods_test

6. 寫在最後

本篇主要討論了計算(數據開發)過程中double類型精度問題,maxcompute在數據集成的過程中會不會產生精度問題?最佳實踐是什麼?預知後事如何,且聽下回分解!

參考文檔

[1] https://blog.csdn.net/liliuteng/article/details/8062019
[2] https://cloud.tencent.com/developer/article/1468551
[3] https://blog.csdn.net/lkforce/article/details/81564927
[4] https://www.zhihu.com/question/42024389/answer/93528601
[5] https://help.aliyun.com/product/27797.html?spm=a2c4g.11186623.6.540.615f44f675F7Wi
[6] https://baike.baidu.com/item/IEEE%20754/3869922?fr=aladdin

我們是阿里雲智能全球技術服務-SRE團隊,我們致力成為一個以技術為基礎、面向服務、保障業務系統高可用的工程師團隊;提供專業、體系化的SRE服務,幫助廣大客戶更好地使用雲、基於雲構建更加穩定可靠的業務系統,提升業務穩定性。我們期望能夠分享更多幫助企業客戶上雲、用好雲,讓客戶雲上業務運行更加穩定可靠的技術,您可用釘釘掃描下方二維碼,加入阿里雲SRE技術學院釘釘圈子,和更多雲上人交流關於雲平臺的那些事。

image.png

Leave a Reply

Your email address will not be published. Required fields are marked *