请选择 进入手机版 | 继续访问电脑版
 找回密码
 立即注册

QQ登录

只需一步,快速开始

硕㏒

金牌服务用户

62

主题

168

帖子

544

积分

金牌服务用户

积分
544
硕㏒
金牌服务用户   /  发表于:2025-3-10 11:17  /   查看:117  /  回复:10
1金币
本帖最后由 硕㏒ 于 2025-3-10 11:20 编辑

image.png740505676.png

E1 单元格的值为19.69;
F1 单元格的值为19.6;
E3 单元格的公式为:=(E1+F1)/2 运算得出的值为 19.645;
F3 单元格的公式为:=IF(AND(MOD(E3*100,1)=0.5,ISEVEN(TRUNC(E3*100))),TRUNC(E3,2),ROUND(E3,2)) 运算得出的值为 19.64;
F4 单元格的公式为:=IF(AND(MOD((E1+F1)/2*100,1)=0.5,ISEVEN(TRUNC((E1+F1)/2*100))),TRUNC((E1+F1)/2,2),ROUND((E1+F1)/2,2)) 运算得出的值为 19.65;
相同的运算公式,为什么得出的值是不一样的?


最佳答案

查看完整内容

请问您所说的“四舍六入五成双”是要对单元格的值进行修改,还是说只要格式化就好? 函数的方式是直接修改了单元格的值,这个值可以参与后续的运算。 单元格格式化只是看起来变化了而已,单元格的真实值并没有变化,而单元格的格式化效果也可以自定义,内部逻辑和我发的自定义函数差不多。 所以您问的这个问题,SpreadJS可以做到在您框选的地方增加一个选项,点击这个选项的效果仍然是代码写的,所以可以是上述两种效果的任意 ...

10 个回复

倒序浏览
最佳答案
最佳答案
Matthew.Xue
超级版主   /  发表于:2025-3-10 11:17:08
来自 7#
本帖最后由 Matthew.Xue 于 2025-3-10 14:33 编辑
硕㏒ 发表于 2025-3-10 14:01
可以在这个地方,新增一个数据格式,实现对单元格的修约吗

请问您所说的“四舍六入五成双”是要对单元格的值进行修改,还是说只要格式化就好?
函数的方式是直接修改了单元格的值,这个值可以参与后续的运算。
单元格格式化只是看起来变化了而已,单元格的真实值并没有变化,而单元格的格式化效果也可以自定义,内部逻辑和我发的自定义函数差不多。
所以您问的这个问题,SpreadJS可以做到在您框选的地方增加一个选项,点击这个选项的效果仍然是代码写的,所以可以是上述两种效果的任意一种,您自行实现即可。
关于如何在您框选的地方增加一个选项,您可以参考这个demo:
设计器增加二级菜单
demo中是直接在这里增加了一个菜单
image.png833227538.png
您可以认真观察一下GC.Spread.Sheets.Designer.DefaultConfig中ribbon的结构,在ribbon[0].buttonGroups[4].commandGroup.children[0].children中push一个命令即可,命令的注册方式与demo中相同。
image.png239402770.png


回复 使用道具 举报
不吐葡萄皮
初级会员   /  发表于:2025-3-10 11:50:54
2#
我试了一下,设置GC.Spread.CalcEngine.ExcelCompatibleCalcMode = true; 之后和Excel结果是一样的,F3和F4都是19.65

设置前,公式=MOD(E3*100,1)=0.5都不一样  SpreadJS 结果是TRUE , Excel 的结果是false。
回复 使用道具 举报
Matthew.Xue
超级版主   /  发表于:2025-3-10 12:06:37
3#
本帖最后由 Matthew.Xue 于 2025-3-10 12:09 编辑

您好,您遇到的这个问题是典型的浮点数精度问题。
两个公式看起来相同,但是得到了不同的结果,这是因为F4中的“MOD((E1+F1)/2*100,1)”结果是0.500000000000227,从而导致“MOD((E1+F1)/2*100,1)=0.5”的结果为false,进而让if进入了else的结果。
而在F3中,您没有使用加减法,也就不会遇到浮点数的精度问题,and结果为true,if没有进入else,从数学逻辑上来说,这一个结果是正确的。
浮点数的精度问题在前后端是普遍存在的,甚至在Excel中,也存在大量的因为浮点数精度问题导致的公式计算错误的情况。

这里给您提供两个方案:
1. 让两个公式保持一致的错误,即开启Excel兼容计算模式,并重新计算:
  1. GC.Spread.CalcEngine.ExcelCompatibleCalcMode = true
  2. spread.calculate()
复制代码
这种方式,两个公式的结果都是19.65

2. 让两个公式保持一致的正确,这种情况下您需要修改公式,将F4的公式修改为:
  1. =IF(AND(ROUND(MOD((E1+F1)/2*100,1),12)=0.5,ISEVEN(TRUNC((E1+F1)/2*100))),TRUNC((E1+F1)/2,2),ROUND((E1+F1)/2,2))
复制代码
这种方式,两个公式的结果都是19.64

回复 使用道具 举报
硕㏒
金牌服务用户   /  发表于:2025-3-10 13:43:08
4#
Matthew.Xue 发表于 2025-3-10 12:06
您好,您遇到的这个问题是典型的浮点数精度问题。
两个公式看起来相同,但是得到了不同的结果,这是因为F4 ...

上面的公式其实是一个修约公式,修约规则是四舍六入五成双的规则,即:

1、被修约的数字小于5时,该数字舍去;
2、被修约的数字大于5时,则进位;
3、被修约的数字等于5时,要看5前面的数字,若是奇数则进位,若是偶数则将5舍掉,即修约后末尾数字都成为偶数;若5的后面还有不为“0”的任何数,则此时无论5的前面是奇数还是偶数,均应进位。
有什么其他好的办法对数值进行修约吗?目前我们采用的方法是吧计算公式套入以下公式F37单元格的位置
四舍六入五成双公式:适用于精确至0.01这种场景
=IF(AND(MOD(F37*100,1)=0.5,ISEVEN(TRUNC(F37*100))),TRUNC(F37,2),ROUND(F37,2))
适用于精确至0.1场景:=IF(AND(MOD(F37*10,1)=0.5,ISEVEN(TRUNC(F37*10))),TRUNC(F37,1),ROUND(F37,1))适用于精确整数=IF(AND(MOD(F37,1)=0.5,ISEVEN(TRUNC(F37))),TRUNC(F37,0),ROUND(F37,0))适用于精确至0.001场景:=IF(AND(MOD(F37*1000,1)=0.5,ISEVEN(TRUNC(F37*1000))),TRUNC(F37,3),ROUND(F37,3))适用于精确至0.0001场景:
=IF(AND(MOD(F37*10000,1)=0.5,ISEVEN(TRUNC(F37*10000))),TRUNC(F37,4),ROUND(F37,4))

回复 使用道具 举报
Matthew.Xue
超级版主   /  发表于:2025-3-10 13:58:38
5#
硕㏒ 发表于 2025-3-10 13:43
上面的公式其实是一个修约公式,修约规则是四舍六入五成双的规则,即:

1、被修约的数字小于5时,该数 ...

您好,您可以通过自定义公式来实现四舍六入五成双的效果,这边给您提供一个现成的demo,您可以测试一下:
自定义公式——四舍六入
回复 使用道具 举报
硕㏒
金牌服务用户   /  发表于:2025-3-10 14:01:53
6#
Matthew.Xue 发表于 2025-3-10 13:58
您好,您可以通过自定义公式来实现四舍六入五成双的效果,这边给您提供一个现成的demo,您可以测试一下: ...

image.png354058837.png

可以在这个地方,新增一个数据格式,实现对单元格的修约吗
回复 使用道具 举报
硕㏒
金牌服务用户   /  发表于:2025-3-10 14:38:30
8#
Matthew.Xue 发表于 2025-3-10 14:32
请问您所说的“四舍六入五成双”是要对单元格的值进行修改,还是说只要格式化就好?
函数的方式是直接修 ...

明白您的意思了,我这边需要的是修约值,而不是像格式化一样只是看起来值改变了,实际参与运算的值并没有改变
回复 使用道具 举报
Matthew.Xue
超级版主   /  发表于:2025-3-10 15:04:09
9#
硕㏒ 发表于 2025-3-10 14:38
明白您的意思了,我这边需要的是修约值,而不是像格式化一样只是看起来值改变了,实际参与运算的值并没有 ...

是的,那您就要用公式函数了。请问还有什么问题可以帮到您呢?
回复 使用道具 举报
硕㏒
金牌服务用户   /  发表于:2025-3-10 15:07:31
10#
Matthew.Xue 发表于 2025-3-10 15:04
是的,那您就要用公式函数了。请问还有什么问题可以帮到您呢?

不用了,谢谢您的帮忙
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 立即注册
返回顶部