【问题标题】:Find closest number from uniform grid从统一网格中找到最接近的数字
【发布时间】:2014-02-17 10:55:30
【问题描述】:

我有一个整数正数n。比如说n=5。如果我们查看 n 的倍数,我们会看到这些数字(我们称之为 n-grid)[... -15, -10, -5, 0, 5, 10, 15, ...]。现在我需要编写一个函数F(n, N),给定一个整数N,从那个n-grid输出一个最接近的数字。例如,F(n, 0) = 0(对于任何 n)。 F(5, 4) = 5F(5, 7) = 5F(5, 8) = 10F(5, -13) = -15 等等。

我写了这个函数:

int const x = ((::abs(N) + (n / 2)) / n) * n;
if (N > 0)
{
    return x;
}
else
{
    return -x;
}

它似乎有效,但不喜欢它的外观。有人可以提出任何改进建议吗?

【问题讨论】:

  • F(4,2)的结果是什么? IE。这种舍入方法是向上还是向下舍入?那么 F(4,-2) 呢?它是向上取整还是远离零?
  • 如果您只是想改善外观,这应该是一个品味问题。您可以更改为: int const x = (N>0?1:-1)*(::abs(N) + (n / 2)) / n) * n;

标签: c++ algorithm


【解决方案1】:

您可以通过将 x 乘以 (N/abs(N)) 并立即返回计算值来摆脱 if 语句,甚至无需将其保存在 x 中。

我不会这样做,因为它会损害可读性。

【讨论】:

    【解决方案2】:

    这可能很容易理解并且看起来很均匀,

    int grid(int n, int N){
       if (N == 0) return N; 
       return n * (N > 0 ? (n + N)/n : (n + abs(N))/n );
    }
    

    这是ideone 结果。

    【讨论】:

      【解决方案3】:
      int closest_number(int n,int N)
      {
          if(N==0)
              return N;
          else if(N > 0)
          {
             int temp = N % n;
             if(temp > (n/2))
                 return (n*((N/n)+1));
             else
                 return (n*(N/n));
          }
          else
          {
              int temp = N % n;
              if(abs(temp) > (n/2))
                  return (n*((N/n)-1));
              else
                  return (n*(N/n));
          }
      }
      

      您可以在此处http://ideone.com/NlJiPt 找到给定测试用例集的 ideone 输出

      【讨论】:

        【解决方案4】:

        这是简单的数学解决方案:-

        F(k,x) = (x/k)*k      if  abs(x-(x/k)*k) <= k/2
        
        
               = (x/k)*k + sign(x)*k    otherwise
        

        C 实现:-

        #include<stdio.h> 
        #include<math.h>
        
        int func(int k,int x) {
        
         int a = (x/k)*k; 
         int sign = x/abs(x); 
        
          if(abs(x-a)<=k/2) 
             return(a); 
        
          else return(a+sign*k); 
        
        }
        
        int main() {
        
         printf("%d",func(5,121));
         return 0;
        } 
        

        【讨论】:

        • 让 k = 5, x = 6. abs(6-6/5)
        • 设 k = 5, x = 121。abs(121-121/5)=abs(121-24) > 5/2。你的公式给出 (121/5)*5 + sign(121)*5 = 125 这是错误的。正确答案是 120。
        • @Nick 很抱歉再次忘记在不等式中乘以 k。检查我的编辑
        【解决方案5】:

        您正在描述一种舍入算法;您需要指定舍入是否对称,然后是向上还是向下(或朝向/远离零对称)。 ideone demo 以下代码。

                                                               // F(4, 6)    F(4, -6)
        int symmetricTowardZero(int n, int N) {
            return n * (int)(N / n);                           //    4         -4
        }
        
        int symmetricAwayFromZero(int n, int N) {
            return n * (int)(N / n + (N < 0 ? -0.5 : +0.5));   //    8         -8
        }
        
        int unsymmetricDownward(int n, int N) {
            return n * floor((double)N / n);                   //    4         -8
        }
        
        int unsymmetricUpward(int n, int N) {
            return n * ceil((double)N / n);                    //    8         -4
        }
        

        【讨论】:

          猜你喜欢
          • 2013-09-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-11-03
          • 2012-06-02
          相关资源
          最近更新 更多