【问题标题】: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。

标签: c++ conditional divide-by-zero floating-point-exceptions


【解决方案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
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 2021-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多