先上代码示例,如下:
1.算数操作符%取余
scala> 11.0 % 4.0
res1: Double = 3.0
2.IEEE 754 取余
scala> math.IEEEremainder(11.0,4.0)
res2: Double = -1.0
从算数操作符得到的余数跟IEEE754标准定义下的不同。IEEE754的余数再计算时用的是四舍五入,而不是截断。因此得到的结果并不一样。
那么?从哪里你体现出IEEE754的四舍五入呢?还有,从哪里体现算术操作符的截断呢?看下面:
算术操作符的运算公式:
Remainder = (Math.Abs(dividend) - (Math.Abs(divisor) *
(Math.Floor(Math.Abs(dividend) / Math.Abs(divisor))))) *
Math.Sign(dividend)
IEEERemainder 方法的公式
IEEERemainder = dividend - (divisor * Math.Round(dividend / divisor))
公式参考于.NET Framework4.8官方文档,经过手动计算,符合验证。建议大家也手动计算测试。
公式解释,使用Java里Math的静态方法说明(因Scala与Java有着同血脉关系):
Math.abs():取绝对值
Math.floor():返回小于或等于一个给定数字的最大整数(向下取最大整数)
Math.sign():返回一个数字的符号, 指示数字是正数,负数还是零,如下:
(1).如果参数为正数,返回1
(2).如果参数为负数,返回-1
(3).如果参数为0,返回0
(4).如果参数为-0,返回-0
(5).如果其他值,返回NaN
Math.round(): 四舍五入的原理是在参数上加0.5然后进行下取整。
注:四舍六入五成双:
当有效位数确定后,其后面多余的数字应该舍去,只保留有效数字最末一位,这种修约(舍入)规则是“四舍六入五成双”,也即“4舍6入5凑偶”这里“四”是指≤4 时舍去,”六”是指≥6时进上,”五”指的是根据5后面的数字来定,当5后有数时,舍5入1;当5后无有效数字时,需要分两种情况来讲:①5前为奇数,舍5入1;②5前为偶数,舍5不进。(0是偶数)
到这大概就明白四舍五入和截断了,从公式上四舍五入就体现在Math.round()方法,而阶段就体现在Math.floor()方法上了。
一个关于程序员杂谈的公众号,欢迎关注!
有不足之处望留言指正
——————END——————
Programmer:柘月十七