在没有太多条件的情况下如何避免除以零?
Posted
技术标签:
【中文标题】在没有太多条件的情况下如何避免除以零?【英文标题】:How can I avoid dividing by zero without too many conditionals? 【发布时间】:2018-11-03 09:00:21 【问题描述】:我有一个整数参数,它应该控制在特定运行中事件发生的次数。
例如,如果每次运行的迭代次数为 1000 次,那么如果我想让事件每 200 次迭代发生一次,则参数 FREQ
将为 5。但是,我希望能够更改迭代次数,但保持比率不变,并且如果我根本不希望事件发生,还能够将 FREQ
参数设置为 0。
这是我目前使用的:
int N_ITER = 1000;
int FREQ = 5;
void doRun()
int count = 0;
for (int i = 0; i < N_ITER; ++i)
if (FREQ > 0)
if (count < N_ITER/FREQ)
doSomething();
count++;
else
doSomethingElse();
count = 0;
else
doSomething();
这很好用,但它不适合我有嵌套条件,特别是当我有两个doSomething()
时,我觉得它应该比这更容易完成。
我尝试将 if (FREQ > 0 && count < N_ITER/FREQ)
设为有条件的,但显然由于被零除而抛出了 Floating point exception
。
我也尝试使用 try/catch 块,但就混乱而言,使用嵌套条件句确实没有什么不同。这个问题有更优雅的解决方案吗?
【问题讨论】:
“我尝试将一个条件设为if (FREQ > 0 && count < N_ITER/FREQ)
,但显然由于被零除而引发了浮点异常。” 这是不可能的。如果FREQ > 0
为假,&&
将短路并阻止对N_ITER/FREQ
的评估。
continue
有助于减少嵌套
另外,请注意,尽管名称为“浮点异常”,但它实际上并不是一个异常,您不能catch
它。相反,它是signal。
@janm 积分除以零可以提高SIGFPE
。演示:coliru.stacked-crooked.com/a/3b7791e2684a52a2
@HolyBlackCat 令人着迷。在这种情况下,浮点除以零可能会返回 NaN。
【参考方案1】:
重新排列条件怎么样?代替count < N_ITER/FREQ
,使用count*FREQ < N_ITER
。如果FREQ = 0
,表达式仍然为真。
int N_ITER = 1000;
int FREQ = 5;
void doRun()
int count = 0;
for (int i = 0; i < N_ITER; ++i)
if (count*FREQ < N_ITER)
doSomething();
count++;
else
doSomethingElse();
count = 0;
【讨论】:
这可能会由于有符号整数溢出而导致不同类型的 UB。 @VTT 好吧,这一切都取决于N_ITER+FREQ
的最大值,这在 OP 的示例中远远不够大。另外,类型总是可以改成更大的,比如unsigned long
。以上是关于在没有太多条件的情况下如何避免除以零?的主要内容,如果未能解决你的问题,请参考以下文章