Sql-Server

關於十進制算術的問題

  • October 15, 2018

我認為我對精度與比例的理解可能不正確,因為以下範例產生的值對我來說沒有意義。decimal(32, 14)將結果四捨五入到小數點後 6 位,而decimal(18, 14)四捨五入到 19。我對小數的理解是decimal(p, [s]),其中p是總位數,s是小數點後的位數(ig,decimal(10, 2)將導緻小數點左側 8 位和右邊的 2 位數字)。這不正確嗎?

我創建了一個小例子來說明看似奇怪的行為:

--------------------
-- Truncates at pipe
-- 1.043686|655...
--------------------
declare @dVal1 decimal(32, 14) = 10
declare @dVal2 decimal(32, 14) = 9.581419815465469

select @dVal1 Val1, @dVal2 Val2, @dVal1 / @dVal2 CalcResult

----------------
-- Most accurate
----------------
declare @dVal3 decimal(18, 14) = 10
declare @dVal4 decimal(18, 14) = 9.581419815465469

select @dVal3 Val3, @dVal4 Val4, @dVal3 / @dVal4 CalcResult

那麼問題來了,我缺少什麼來理解這一點?我讀過的文章和 msdn 部落格似乎並沒有提供清晰的資訊(至少在我的思考過程中)。有人可以向我解釋為什麼更高的精度似乎會導致規模損失嗎?

您的理解是正確的,儘管您的數字太多了@dVal2@dVal4這就是為什麼您看到這些數字被四捨五入到 7 ( 9.58141981546547) 作為您的最後一位數字select

至於除法舍入,它隱藏在文件中間。

在乘法和除法運算中,我們需要精確的比例位置來儲存結果的整數部分。可以使用以下規則縮小比例:

如果積分部分小於 32,則生成的比例將減少到 min(scale, 38 – (precision-scale)),因為它不能大於 38 – (precision-scale)。在這種情況下,結果可能會四捨五入。

小於 6 且整數部分大於 32 的小數位數不會改變。這種情況下,如果不能放入小數(38,小數位數),可能會引發溢出錯誤

如果比例大於 6 且整數部分大於 32,則比例將設置為 6。在這種情況下,整數部分和比例都會減小,結果類型為小數(38,6)。結果可能會四捨五入到小數點後 6 位,如果整數部分不能容納 32 位,則會引發溢出錯誤。

因此,在您的第一種情況下decimal(32,14),比例設置為 6 位,因為結果值decimal(64,28)的 a scale = 28> 6 並且整數部分(64-28) = 36> 32,如上面最後一條規則中所定義。因此,decimal(38,6)

在您的第二種情況下decimal(18,14),第一條規則被應用於您的比例,以獲得decimal(36,28)to的結果值min(28, 38 -(36-28)) = min(28,30) = 28。因此,decimal(38,28)

引用自:https://dba.stackexchange.com/questions/220165