ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 56739|回复: 28

[分享]VBA四舍五入函数round()的一些不同

[复制链接]

TA的精华主题

TA的得分主题

发表于 2007-9-7 13:14 | 显示全部楼层 |阅读模式

四舍五入对于我们来说再熟悉不过了,但这次却碰到一个麻烦的问题。

由于实行全员个人所得税申报,从地税拿到了个人所得税申报软件,按要求把数据都导入后,软件计算出所有职工的当月个人所得税。由于我们发工资有一套自行开发的系统,这里面也有一个计税的模块,因此我就把两个系统的计税结果进行了比较,比较结果是总金额差3分钱。这3分钱对于我们来说可以忽略不计,但对于财务来说那可就麻烦了,相信做财务的人会有体会。(本人不是财务,是做人力资源的)

通过vlookup很快找到了有3个人地税系统中计税多1分钱,然后重点对这3个人的数据进行了分析。由于工资系统不是我写的,于是用VBA写了一个计税模块,结果发现我的计算结果和工资系统一致,比地税的系统差1分钱。跟踪了一下VBA代码发现在对结果进行四舍五入前税是13.765,进行四舍五入后结果为13.76,这个结果和我们按一贯的思路来说就不对了。

这时我想起了读书时老师讲过的另一种四舍五入方法,也就是“四舍六入,五判断,五前是奇则进,五前为偶不进”,简单的说就是“奇进偶不进”(这是我们老师教的,现在知道还有一点的不足)。于是在VBA中又测试了一些数据,果然VBA是按后面的方法来做四舍五入的。
上网查了资料,这个四舍五入法是一个国际标准,大部分的编程软件都使用的是这种方法,这种方法还有个名字叫“银行家舍入”,据说国际上一般都是用这种方法的。

原来如此,看来我找到问题的原因了,激动ing。

接下来,就是想办法找一个真正的四舍五入的算法。
想到一个以前用来向上取整的方法,试试吧。int(13.765*100+0.5)/100
按理来说,这样计算后应该能得到13.77,但实际函数返回结果还是13.76。why?

在VBA的立即窗口中计算

?int(13.765*100+0.5)/100
13.77

怎么是正确的呢,真有点搞糊涂了,明明是进位了,但为什么代码中出来的数据就不进位了呢?

分析一下,立即窗口直接计算和代码返回的值可能不一样,因为代码返回的是一个浮点型数据,而浮点型数据在计算机中存放的是一个近似数,13.765也许机器内存放的是类似13.76499999999这样的一个数,因此加0.5也并没有进位,再取整当然还是不行。

网络真好,又找到一条信息使我对银行家舍入又有了新的认识,上面提到的方法还不完全,实际应该是“四舍六入,五判断,五后非零则进入,五后为零再判断,五前是奇则进,五前为偶不进”。

继续,接着搜索。功夫不负有心人,终于找到一个方法,对于银行家舍入法转换为普通四舍五入的一个巧方法是先加一个很小的数,然后进行四舍五入。我试着用Round(所得税计算(275.3, 0)+0.00001, 2),结果成功了,得到了13.77这个答案。兴奋ing。这个方法其实就是把5后为0的情况变成5后非零,于是就进上去了。达到了“四舍五入”的要求,所以这个方法我觉得不错。


问题到此基本解决!:)


附上我的所得税算法。有兴趣的朋友可以试试。
给三个我碰到问题的数据

月收入       起征额
3376         1121.45+1600
2752         1043.1+1600
3037         1161.7+1600


Public Function 所得税计算(月收入 As Double, 起征额 As Double)

'函数名:所得税计算() 返回double型
'
'功能:
'    计算个人收入调节税 ""
'
'参数:
'    月收入(double)
'    起征额(double)"
'
'编写日期:2006-01-13
'最后修改日期:2007-9-7
'编写人: 小熊加加

'国家规定的起征额(1600元)

    Dim basicm As Double
    Dim sl As Double
    Dim sskcs As Integer
   
    basicm = 月收入 - 起征额
   
   
    '计算适用税率及速扣数       '修改此段,提高效率 2007-3-2
    If basicm <= 0 Then
        sl = 0
        sskcs = 0
    ElseIf basicm <= 500 Then
        sl = 0.05
        sskcs = 0
    ElseIf basicm <= 2000 Then
        sl = 0.1
        sskcs = 25
    ElseIf basicm <= 5000 Then
        sl = 0.15
        sskcs = 125
    ElseIf basicm <= 20000 Then
        sl = 0.2
        sskcs = 375
    ElseIf basicm <= 40000 Then
        sl = 0.25
        sskcs = 1375
    ElseIf basicm <= 60000 Then
        sl = 0.3
        sskcs = 3375
    ElseIf basicm <= 80000 Then
        sl = 0.35
        sskcs = 6375
    ElseIf basicm <= 100000 Then
        sl = 0.4
        sskcs = 10375
    Else
        sl = 0.45
        sskcs = 15375
    End If
   
   
    所得税计算 = Round(basicm * sl - sskcs + 0.00000001, 2)

End Function

[此贴子已经被作者于2008-3-21 9:54:25编辑过]

TA的精华主题

TA的得分主题

发表于 2007-9-7 13:31 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助

Sub aa()

MsgBox Round(13.765, 2)                               '--- 显示 13.76 (特殊四舍五入)
MsgBox Application.WorksheetFunction.Round(13.765, 2) '--- 显示 13.77 (普通四舍五入)

MsgBox Round(13.775, 2)                               '--- 显示 13.78 (特殊四舍五入)
MsgBox Application.WorksheetFunction.Round(13.775, 2) '--- 显示 13.78 (普通四舍五入)

End Sub

TA的精华主题

TA的得分主题

发表于 2007-9-7 14:02 | 显示全部楼层

关于四舍六入的五奇进偶舍,我用的是函数公式,呵呵,比较笨的方法~~~~~比如:

要保留N位小数,则分别截取第N及N+1位,然后,再判断是奇数还是偶数,再进位~~~~

呵呵,象天书吧~~~

下次再传例子吧,今天有点忙~~~

再有,我的版本,round并不完全是四舍六入的五奇进偶舍的,碰到5的时候,是随机取舍的~~~~

TA的精华主题

TA的得分主题

 楼主| 发表于 2007-9-7 16:29 | 显示全部楼层
QUOTE:
以下是引用xtutu520在2007-9-7 14:02:17的发言:

关于四舍六入的五奇进偶舍,我用的是函数公式,呵呵,比较笨的方法~~~~~比如:

要保留N位小数,则分别截取第N及N+1位,然后,再判断是奇数还是偶数,再进位~~~~

呵呵,象天书吧~~~

下次再传例子吧,今天有点忙~~~

再有,我的版本,round并不完全是四舍六入的五奇进偶舍的,碰到5的时候,是随机取舍的~~~~

碰到5并不是随机取舍的,首先如果5后面的数不为零,那么进位。如果5后面数为零,则判断5前面的数,如果是奇数则时位,偶数则不进位。

round(1.4501,1)----->1.5     因5后面的数不为零,这里直接进位,不考虑5前面数的奇偶(现在网上的绝大多数的资料中都没提到这一点,但我在VBA中测试,的确是这样的)

round(1.45,1)------>1.4    因5后的数为零,故考虑5前的数,因5前的数为4,是偶数,所以不进位,因此得到1.4

round(1.35,1)------>1.4   因5后的数为零,故考虑5前的数,因5前的数为3,是奇数,所以进位,因此得到1.4

TA的精华主题

TA的得分主题

发表于 2007-9-7 17:29 | 显示全部楼层

怎么看完了后还像看天书一样呢?

[em04]

TA的精华主题

TA的得分主题

发表于 2007-9-7 17:43 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
QUOTE:
以下是引用lbpp在2007-9-7 16:29:28的发言:

碰到5并不是随机取舍的,首先如果5后面的数不为零,那么进位。如果5后面数为零,则判断5前面的数,如果是奇数则时位,偶数则不进位。

round(1.4501,1)----->1.5     因5后面的数不为零,这里直接进位,不考虑5前面数的奇偶(现在网上的绝大多数的资料中都没提到这一点,但我在VBA中测试,的确是这样的)

round(1.45,1)------>1.4    因5后的数为零,故考虑5前的数,因5前的数为4,是偶数,所以不进位,因此得到1.4

round(1.35,1)------>1.4   因5后的数为零,故考虑5前的数,因5前的数为3,是奇数,所以进位,因此得到1.4

round(1.45,1)------>1.4    因5后的数为零,故考虑5前的数,因5前的数为4,是偶数,所以不进位,因此得到1.4

round(1.35,1)------>1.4   因5后的数为零,故考虑5前的数,因5前的数为3,是奇数,所以进位,因此得到1.4

这是在哪里面得到的结果中,我在单元格中输入ROUND(1.45,1)=1.5哟

TA的精华主题

TA的得分主题

 楼主| 发表于 2007-9-7 18:11 | 显示全部楼层
QUOTE:
以下是引用blue_prince在2007-9-7 17:43:22的发言:

round(1.45,1)------>1.4    因5后的数为零,故考虑5前的数,因5前的数为4,是偶数,所以不进位,因此得到1.4

round(1.35,1)------>1.4   因5后的数为零,故考虑5前的数,因5前的数为3,是奇数,所以进位,因此得到1.4

这是在哪里面得到的结果中,我在单元格中输入ROUND(1.45,1)=1.5哟

EXCEL工作表中的round()函数是按通常习惯的四舍五入来工作的,而VBA中的round()函数才是我上面说的“四舍六入五判断”的方式工作的。

TA的精华主题

TA的得分主题

发表于 2007-9-8 11:18 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助

以前我们的老师是说4舍6入5留双的,没想到还有这么复杂,的浮点问题

不过差一两分钱的事情,不同的情况真不同.

TA的精华主题

TA的得分主题

发表于 2008-8-27 15:56 | 显示全部楼层
长进,开眼界。真的是这样

TA的精华主题

TA的得分主题

发表于 2008-8-27 19:28 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
不错,学习了
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-9-29 20:32 , Processed in 0.036446 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表