ASP.NET Decimal, Double 四捨五入

Decimal 帶正負號十進位值是 Data Type 數據類型,用於表示精確的小數值。十進制 Decimal 非整數數值資料類型可以保存帶正負號的 128 位元 (十六位元組) 16 Bits 值。Decimal 值適合用於財務計算或需要高精度的場合。需要大量數位但無法容許捨入錯誤的財務計算。

Decimal 十進位值

Decimal「帶 ± 正負號」十進位值。
128 位固定點數數值型別。
小數點右邊有 28 位數。( -7922816251426433759354395033579228162514264337593543950335 )

Dim DE As Decimal
DE.MaxValue = 79228162514264337593543950335 'Decimal 最大值
DE.MinValue = -79228162514264337593543950335 'Decimal 最小值
Dim DE As Decimal = 18.4555
Math.Round(DE) = 18
Math.Round(DE, 2) = 18.46
Math.Round(DE, 3) = 18.456
Math.Round(DE, MidpointRounding.ToEven) = 18
Math.Round(DE, 3, MidpointRounding.AwayFromZero) = 18.456


MidpointRounding 指定四捨五入的方式

MidpointRounding.AwayFromZero 而當數位在兩個數字「中間點值」會四捨五入到最接近零的數位。
MidpointRounding.ToEven 當數位在兩個數字「中間點值」會四捨五入到最接近的偶數。

分析 MidpointRounding.ToEven 四捨六入五取偶
銀行家算法:四捨六入五考慮,五後非零就進一,五後為零看奇偶,五前為偶應捨去,五前為奇要進一。四捨六入五取偶是比較精確比較科學的數字修約方法,用於減少捨入誤差的影響。這種方法在化學、統計等領域廣泛使用,因為它可以使測量結果更接近真實值,而不是如 Rounding 四捨五入那樣偏向大數或小數。

Math.Round(1.5, MidpointRounding.ToEven) '返回 2
Math.Round(2.5, MidpointRounding.ToEven) '返回 2
Math.Round(3.5, MidpointRounding.ToEven) '返回 4
Math.Round(4.5, MidpointRounding.ToEven) '返回 4
Math.Round(5.5, MidpointRounding.ToEven) '返回 6
Math.Round(6.5, MidpointRounding.ToEven) '返回 6

AwayFromZero 正數

Math.Round(1.4, MidpointRounding.AwayFromZero) '返回 1
Math.Round(1.5, MidpointRounding.AwayFromZero) '返回 2
Math.Round(1.6, MidpointRounding.AwayFromZero) '返回 2

AwayFromZero 負數

Math.Round(-1.4, MidpointRounding.AwayFromZero) '返回 -1
Math.Round(-1.5, MidpointRounding.AwayFromZero) '返回 -2
Math.Round(-1.6, MidpointRounding.AwayFromZero) '返回 -2


數值取捨的不同方式

Math.Round(DE) = 18 '進位值四捨五入到最接近的整數值
Math.Ceiling(DE) = 19 '返回「大於或等於」的最小整數值。
Math.Floor(DE) = 18 '返回「小於或等於」的最大整數值。
Math.Truncate(DE) = 18 '返回數字的「整數部分」

Double 雙精度浮點數

Double「帶 ± 正負號」雙精度浮點數。
64 位浮點數數值型別。
-1.79769313486232E+3081.79769313486232E+308

DO.MaxValue = 1.79769313486232E+308 'Double 最大值
DO.MinValue = -1.79769313486232E+308 'Double 最小值
Dim DO As Decimal = 18.4555
Math.Round(DO) = 18
Math.Round(DO, 2) = 18.46
Math.Round(DO, 3) = 18.456
Math.Round(DO, MidpointRounding.ToEven) = 18
Math.Round(DO, 3, MidpointRounding.AwayFromZero) = 18.456
Math.Round(DO) = 18
Math.Ceiling(DO) = 19
Math.Floor(DO) = 18
Math.Truncate(DO) = 18

整理 ASPX 比較以上 Decimal, Double 數值看起來一樣,但在官網上看到計算差異。

Decimal 類型計算結果

1 / 3 * 3 = 0.9999999999999999999999999999

Double, Single 類型計算結果

1 / 3 * 3 = 1

ASPX 相關 Decimal 數值處理

Dim DE As Decimal = Decimal.One '表示數字為 1
Dim DE As Decimal = Decimal.Zero '表示數字為 0
Dim DE As Decimal = Decimal.MinusOne '表示數字為 -1
Decimal.Multiply(Decimal, Decimal) 相乘方法。
Decimal.Divide(Decimal, Decimal) 相除方法。
Decimal.Remainder(Decimal, Decimal) 相除後的餘數。
Decimal.Subtract(Decimal, Decimal) 相減方法。
Decimal.Negate(Decimal, Decimal) 變換「正負號」乘積的值。


ASP.NET, ASPX 相關 Math 數值格式處理

Math.IEEEremainder()

Math.IEEEremainder() 根據 IEEE 754 二進位浮點數算術標準,對「指定的 Number, Divisor 參數」執行除法運算返回餘數。

Math.IEEEremainder(Number, Divisor)

返回 Number - (Base * Divisor),其中 Base 是最接近 Number / Divisor 的整數(四捨五入到最接近的整數值)。
而餘數 Number Mod Divisor 返回 Number - (Base * Divisor),其中 Base 是 Number / Divisor 的「整數部分」。

Math.IEEEremainder(8, 3)
8 / 3 = 2.6666666666666665
Base = Math.Round(2.6666666666666665) = 3
8 - (3 * 3)
8 Mod 3 = 2
Base = Math.Truncate(2.6666666666666665) = 2
8 - (2 * 3)

嘗試用 JavaScript 計算,但小數上有些差異。

let gNumber = 17.8
let gDivisor = 4
let gBase = Math.round(gNumber / gDivisor);
let IEEEremainder = gNumber - (gBase * gDivisor);

1.8000000000000007

Math.IEEEremainder(17.8, 4) '1.8

廣泛為 CPU 與浮點運算器所採用使用的浮點數運算標準,我目前是沒有機會使用到只是研究差異 😛。