SQL 與 C# 的四捨五入

November 23, 2022

本文介紹 SQL 和 C# 兩種語言對於進位、捨去的實作標準,因為跟我們以往學到的有所不同,使用時必須留意。(轉自自己的鐵人賽文章,並稍作修改)

C# 的四捨五入

在 C# 和其它 .Net 語言環境中,使用 Math.Round() 進行四捨五入時,其結果未必與我們所熟悉的四捨五入相同。

Math.round(1.51) = 2
Math.round(1.5) = 2 // 會進位
Math.round(1.49)=1

Math.round(0.51) = 1
Math.round(0.5) = 0 // 不像一般四捨五入會進位
Math.round(0.49)=0

這是因為 .Net 遵循的是 IEEE Standard 754 第 4 節,其捨入方式可稱為:捨入至最接近值、四捨六入五成雙(Banker’s Rounding)

如果要對數值四捨五入的話,應在 Math.Round() 傳入參數 MidpointRounding.AwayFromZero :

Math.round(0.5, MidpointRounding.AwayFromZero); // 結果為 1 (四捨五入)

參考資料: Round 真的是四捨五入嗎 - Jeff 隨手記 - 點部落

SQL Server 的四捨五入

ROUND ( numeric_expression , length)  

numeric_expression 為需要被捨入的數值,length 為捨入的位數。 例如:

ROUND(648.58, -1) -- 650.0
ROUND(23.994, 2) -- 23.99

如果對以下數值四捨五入,會產生溢位錯誤。

ROUND(0.5, 0) -- 預期為 1.0

出現錯誤 :

Msg 8115, Level 16, State 2, Line 2
轉換 expression 到資料類型 numeric 時發生算術溢位錯誤。

應該改成以下語法,事先轉型為 Numeric 或字串,才能正確取得結果:

SELECT ROUND(CAST(0.5 AS NUMERIC(2, 1)), 0)
SELECT ROUND('0.5', 0)

參考資料: