ASP.NET Decimal, Double 四捨五入
Decimal 带正负号十进位值是 Data Type 数据类型,用于表示精确的小数值。十进制 Decimal 非整数数值资料类型可以保存带正负号的 128 位元 (十六位元组) 16 Bits 值。Decimal 值适合用于财务计算或需要高精度的场合。需要大量数位但无法容许捨入错误的财务计算。
Decimal 十进位值
Decimal「带 ± 正负号」十进位值。
128 位固定点数数值型别。
小数点右边有 28 位数。( -79228162514264337593543950335 和 79228162514264337593543950335 )
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+308 和 1.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 与浮点运算器所採用使用的浮点数运算标准,我目前是没有机会使用到只是研究差异 😛。