我正在尝试计算滚动平均值,并试图获得并优化一点,我简化了计算,因此只有一个除法.当值减小时,存在当前值降低到小于平均值的点.此时平均跳跃.我想这是因为除法是无符号的,我的分子符号位被解释为一个大的无符号数.我只是不确定我需要在哪里投贴无符号以确保此问题不再出现.
unsigned int AverageUsage;
unsigned int TotalUsage;
unsigned int incCount;
AverageUsage = (TotalUsage - AverageUsage)/++incCount + AverageUsage;
Run Code Online (Sandbox Code Playgroud)
AverageUsage将始终为正,但当TotalUsage低于AverageUsage时,我不确定该部门会有什么期望
AverageUsage = (signed int)(TotalUsage - AverageUsage)/++incCount + AverageUsage;
Run Code Online (Sandbox Code Playgroud)
将分子设置为已签名,但我不确定如何进行除法.
AverageUsage = (signed int)((signed int)(TotalUsage - AverageUsage)/++incCount) + AverageUsage;
Run Code Online (Sandbox Code Playgroud)
应该工作(我可以保证这个完整操作的结果永远不会是负面的),但我担心incCount达到"看起来"负面的值的情况.
是否有一个简单的解决方案,希望:
谢谢!
C二元OPS(包括分裂)的一般规则是,操作数都将被转换为相同的类型,这是以下之一:int,unsigned int,long,unsigned long,intmax_t,uintmax_t,float,double,long double.如果两个操作数都是该列表中的类型,则它们都将转换为后一个操作数.如果两者都不是,那么它们都将被转换为int
所以在你的例子中:
AverageUsage = (signed int)(TotalUsage - AverageUsage)/++incCount + AverageUsage
Run Code Online (Sandbox Code Playgroud)
if incCountis unsigned int,那么你的强制转换没有效果 - 减法将转换为signed int,然后再回到unisgned int,并且将完成无符号除法.如果您想要签名的部门,您需要:
AverageUsage = (int)(TotalUsage - AverageUsage)/(int)++incCount + AverageUsage
Run Code Online (Sandbox Code Playgroud)
正如您所说,如果incCount超过INT_MAX,您可能会遇到麻烦.
通常,用于除法的处理器指令仅指定一种类型,其用于两个操作数.当存在用于具有不同类型的除法的特殊指令时,其通常用于较大(双倍宽度)的被除数,而不是不同的符号.
你有两个选择。
使用浮点数学
我认为无论如何你都想这样做以获得适当的平均值。
不存在混合浮点数/整数除法这样的东西。因此,分子和分母都将转换为浮点数。
分子或分母是有符号还是无符号并不重要。不存在无符号浮点数这样的东西。分母 incCount 将转换为浮点型,并进行完整的浮点除法。
使用整数除法并处理特殊情况
如果出于某种原因您想保留整数除法,则分子和分母必须是相同的有符号/无符号类型。
分子/分母均带符号
incCount 将转换为有符号数。如果它太大,那么它看起来就像一个负数,你的答案就会是错误的。您必须测试此溢出。
分子/分母都是无符号的
您必须使分子无符号并使用 if () 语句来处理两种情况:TotalUsage < AverageUsage和TotalUsage > AverageUsage。这里 incCount 可以使用整数位的全部范围,因为它将被视为无符号数。