四舍六入五成双规则如下:
1. 被修约的数字小于5时,该数字舍去;
2. 被修约的数字大于5时,则进位;
3. 被修约的数字等于5时,要看5前面的数字,若是奇数则进位,若是偶数则将5舍掉,即修约后末尾数字都成为偶数;若5的后面还有不为“0”的任何数,则此时无论5的前面是奇数还是偶数,均应进位。
举例,用上述规则对下列数据保留小数点后两位数据:
9.8249=9.82, 9.82671=9.83
9.8350=9.84, 9.8351 =9.84
9.8250=9.82, 9.82501=9.83
SET @Val = 9.8250; -- 参数 SET @MinusValue = (@Val * 100 - FLOOR(@Val * 100) = 0.5) / 100; --判断是否需要减去0.01 SELECT ROUND(ROUND(@Val, 2)- @MinusValue, 2) --打印出最终结果
逻辑如上,仅供参考。
额,以上少了判断奇偶数的那个步骤,补上:
SET @Val = 9.8250; -- 参数 SET @MinusValue = (@Val * 100 - FLOOR(@Val * 100) = 0.5) / 100; --判断是否需要减去0.01 SET @PlusValue = FLOOR(@Val * 100) % 2 / 100; -- 判断,如果是奇数,那么加0.01 SELECT ROUND(ROUND(@Val, 2) - @MinusValue + @PlusValue, 2) --打印出最终结果
查看测试了下你提供的方法,判断是否需要减去0.01这个地方,如果前面是奇数的话我们是要加1的。9.825是可以实现,但是9.835就会有问题
@P-1ng: 9.835 输出 9.84,有问题?
@幻天芒: 刚没看到你补充的,你后面判断的是9.835和9.825是没问题了,但没有四舍六入的判断。
@P-1ng: 你自己分析下逻辑吧,不需要四舍六入了,ROUND就是干这事的。
@幻天芒: 嗯的,我瞅瞅,因为ROUND是进行四舍五入的,刚我使用你提供的方法,@val=9.8340 得出的结果是9.84 实际应该是9.83
@P-1ng: 嗯,这个是因为每次都判断了奇偶数导致的,实际上,第一个条件不满足,不需要判断奇偶。所以需要排除掉:
SET @Val = 9.8340; -- 参数 SET @MinusValue = (@Val * 100 - FLOOR(@Val * 100) = 0.5) / 100; --判断是否需要减去0.01 SET @PlusValue = IF(@MinusValue=0, 0, FLOOR(@Val * 100) % 2 / 100); -- 判断,如果是奇数,那么加0.01,当之前的条件不满足时,不需要执行+0.01操作。 SELECT ROUND(ROUND(@Val, 2) - @MinusValue + @PlusValue, 2); --打印出最终结果
@幻天芒: 谢谢,测试了几把可以了,我改成函数就好了
@幻天芒: 亲,有空么,能帮我封装成mysql的函数么,我都醉了,我封装后,结果和你写的测的结果就有差。。。
@幻天芒: 我怀疑的你那个入参的类型问题,我试过float,VARCHAR,DECIMAL都有差别……
@幻天芒: 还有个小问题,如果@val这个参数,是运算出来的,除不尽的如:29.5351/3 计数器得出的结果是9.8450333333……你这个得出的是9.85,实际应是9.84
@P-1ng: 最后一个场景,既然是除不尽的,那么就证明5后面还有值,那就应该升上去,就应该是9.85吧。
@P-1ng: 至于数据类型,理论上不会有太大差异,注意要理解这个写法的含义。
@幻天芒: 对于除不尽的场景,你的说法是正确的。
数据库最好只负责保存数据,业务逻辑写在软件代码中好一些。
9.8350=9.84,
9.8250=9.82,
这两个是互相冲突的吧?
嗯的,现在业务需要使用存储过程处理小部分的业务。
@P-1ng: 逻辑清晰的话,就算是存储过程也没啥大不了的,自己学着写写吧。
这又不是啥难题。我看你写的也算是清楚了。
没有哦,你看规则的3,如果是被约掉的数是5,就看被约数的前一位,是奇数则进1,是偶数则舍去,所以举例 9.8350 保留小数点2位,被舍去的是0.005 碰到5,则看5前面那位,是0.03,也就是奇数则进1,所以9.835 =9.84