C++ 如何有效地表达这个函数

C++ 如何有效地表达这个函数,c++,C++,因此,它向下舍入到下一个mul。但很明显,对于n的大值来说是不好的。如何安全有效地表达它?这相对简单,您只需在调整变量的同时计算变化的表达式,直到结果满足正确的条件: int f(int n, int mul) { if (abs(n)%mul == 0) return n; else return f(n - 1, mul); } 注: 虽然这回答了您的问题,但代码仍然不好,但原因不同: 有些函数对数字进行四舍五入。与其重新发明轮子,不如首先本能地使用其中一种 abs()

因此,它向下舍入到下一个
mul
。但很明显,对于n的大值来说是不好的。如何安全有效地表达它?

这相对简单,您只需在调整变量的同时计算变化的表达式,直到结果满足正确的条件:

int f(int n, int mul) {
    if (abs(n)%mul == 0) return n;
    else return f(n - 1, mul);
}
注:

  • 虽然这回答了您的问题,但代码仍然不好,但原因不同:
    • 有些函数对数字进行四舍五入。与其重新发明轮子,不如首先本能地使用其中一种
    • abs()
      看起来是无辜的,但是如果你给它一个二补系统中可能最小的整数呢?根本没有绝对值可以表示为这样的整数
    • 类似地,递减
      n
      可能会下溢,导致未定义的行为(以及令人惊讶的结果)
    • 另外,如果
      mul
      不是正的,该怎么办?代码不会以任何方式处理这种情况,而函数签名允许这样做
    • 最后但并非最不重要的一点是,首先编写循环是愚蠢的。模运算将给出第一个操作数到第二个操作数下一个倍数的距离!不过,请确保您了解这是如何处理负数的。此外,如果模与某些值一起使用时导致未定义的行为,我也不会感到惊讶。这99%的正确率是容易的,剩下的是棘手的
  • 优化后端递归的编译器可能会生成相同的代码,因此不能保证它会给您带来任何好处

这相对简单,您只需在调整变量的同时计算变化的表达式,直到结果满足正确的条件:

int f(int n, int mul) {
    if (abs(n)%mul == 0) return n;
    else return f(n - 1, mul);
}
注:

  • 虽然这回答了您的问题,但代码仍然不好,但原因不同:
    • 有些函数对数字进行四舍五入。与其重新发明轮子,不如首先本能地使用其中一种
    • abs()
      看起来是无辜的,但是如果你给它一个二补系统中可能最小的整数呢?根本没有绝对值可以表示为这样的整数
    • 类似地,递减
      n
      可能会下溢,导致未定义的行为(以及令人惊讶的结果)
    • 另外,如果
      mul
      不是正的,该怎么办?代码不会以任何方式处理这种情况,而函数签名允许这样做
    • 最后但并非最不重要的一点是,首先编写循环是愚蠢的。模运算将给出第一个操作数到第二个操作数下一个倍数的距离!不过,请确保您了解这是如何处理负数的。此外,如果模与某些值一起使用时导致未定义的行为,我也不会感到惊讶。这99%的正确率是容易的,剩下的是棘手的
  • 优化后端递归的编译器可能会生成相同的代码,因此不能保证它会给您带来任何好处

    • 如果您担心
      堆栈溢出
      。。。那就不要

      下面的函数基本上是一个
      尾部递归
      函数,GCC之类的编译器会自动将其转换为迭代函数

      while (abs(n) % mul != 0) --n;
      
      参考:


    • 希望这有帮助

      如果您担心堆栈溢出。。。那就不要

      下面的函数基本上是一个
      尾部递归
      函数,GCC之类的编译器会自动将其转换为迭代函数

      while (abs(n) % mul != 0) --n;
      
      参考:


    • 希望这有帮助

      如果你的第二个参数是100,它只会四舍五入到100。接下来是一个迭代实现。如果你提供进一步的细节,我可能会再看一遍

      int f(int n, int mul) {
          if (abs(n)%mul == 0) return n;
      
          return f(n - 1, mul);  //Tail recursion
      }
      

      如果你的第二个参数是这样的话,它只会四舍五入到100。接下来是一个迭代实现。如果你提供进一步的细节,我可能会再看一遍

      int f(int n, int mul) {
          if (abs(n)%mul == 0) return n;
      
          return f(n - 1, mul);  //Tail recursion
      }
      

      如何安全高效地表达[递归函数]

      对于非负的
      n
      mul
      您可以

           int f(int n, int mul)
           {
               while(n%mul != 0)
               {
                 n--;
               };
      
           return n;
           }
      
      我将负值的可能调整以及如何处理零
      mul
      ,留给读者

      这是你能得到的最有效的方法;这就是Euclid今天所使用的,他使用了C++而不是[1 ] COBOL。
      另一种选择是

      return n - n%mul;
      
      这比第一种方法的效率高还是低取决于

      但我会认为任何差异都太小了


      你要求的不是最有效率,而只是“有效率”。这意味着合理的效率。尽管如此,我还是建议在关注效率的时候进行测量

      测量不需要很大的努力

      在许多情况下,仅仅观察程序的性能就足够了(分辨率和精度非常低,但通常足够好)


      [1] 不知道确切的原因,但我一直认为欧几里得是一个COBOL的家伙。

      Re

      如何安全高效地表达[递归函数]

      对于非负的
      n
      mul
      您可以

           int f(int n, int mul)
           {
               while(n%mul != 0)
               {
                 n--;
               };
      
           return n;
           }
      
      我将负值的可能调整以及如何处理零
      mul
      ,留给读者

      这是你能得到的最有效的方法;这就是Euclid今天所使用的,他使用了C++而不是[1 ] COBOL。
      另一种选择是

      return n - n%mul;
      
      这比第一种方法的效率高还是低取决于

      但我会认为任何差异都太小了


      你要求的不是最有效率,而只是“有效率”。这意味着合理的效率。尽管如此,我还是建议在关注效率的时候进行测量

      测量不需要很大的努力

      在许多情况下,只是观察