从统一网格中找到最接近的数字

Posted

技术标签:

【中文标题】从统一网格中找到最接近的数字【英文标题】: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; 【参考方案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

【讨论】:

以上是关于从统一网格中找到最接近的数字的主要内容,如果未能解决你的问题,请参考以下文章

将 SDF 计算为三角形网格的最有效方法

在 C++ 中通过网格/矩阵找到成本优化路径

使用 matplotlib 从“列表列表”中绘制 3d 曲面

寻找最长路径网格

剑道网格相当于 onEditComplete

使用 Collider Unity 将线渲染转换为 3d 网格