在没有太多条件的情况下如何避免除以零?

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 &gt; 0 &amp;&amp; count &lt; N_ITER/FREQ) 设为有条件的,但显然由于被零除而抛出了 Floating point exception

我也尝试使用 try/catch 块,但就混乱而言,使用嵌套条件句确实没有什么不同。这个问题有更优雅的解决方案吗?

【问题讨论】:

“我尝试将一个条件设为if (FREQ &gt; 0 &amp;&amp; count &lt; N_ITER/FREQ),但显然由于被零除而引发了浮点异常。” 这是不可能的。如果FREQ &gt; 0 为假,&amp;&amp; 将短路并阻止对N_ITER/FREQ 的评估。 continue 有助于减少嵌套 另外,请注意,尽管名称为“浮点异常”,但它实际上并不是一个异常,您不能catch 它。相反,它是signal。 @janm 积分除以零可以提高SIGFPE。演示:coliru.stacked-crooked.com/a/3b7791e2684a52a2 @HolyBlackCat 令人着迷。在这种情况下,浮点除以零可能会返回 NaN。 【参考方案1】:

重新排列条件怎么样?代替count &lt; N_ITER/FREQ,使用count*FREQ &lt; 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

以上是关于在没有太多条件的情况下如何避免除以零?的主要内容,如果未能解决你的问题,请参考以下文章

如何避免 SQL 中的“除以零”错误?

在没有条件比较的情况下在数学上找到最大值

s-s-rS 2008 - 处理除以零的情况

如何在零停机的情况下迁移 Kubernetes 集群

如何在没有前导零的情况下转换配置单元中的日期

在java中的double和float类型数据相除为啥可以除以零