使用模数运算符保持容器索引内

发布于 2024-11-25 10:10:48 字数 685 浏览 1 评论 0原文

假设我有一个向量 v,其中包含 m 个元素,并且该向量的随机访问索引称为 i。

当我增加索引时,如果它超出范围,我想索引第一个(第零个)元素。同样,当我递减索引时,如果索引 < 0,我想索引到最后一个元素。目前,我一次只在容器中移动一个元素,因此想出了这个函数:

unsigned int GetIndexModM(int index,unsigned int m) {return (index + m) % m;}

调用站点可能如下所示:

std::vector<Whatever> v = ... // initialise with 5 elements
unsigned int i = 0;
unsigned int j = GetIndexModM(static_cast<int>(i) - 1,v.size()); // get preceeding index

但是,如果减去一个值 > ,则该函数将失败。 m 来自索引:

unsigned int j = GetIndexModM(static_cast<int>(i) - 17,v.size()); // oops: returns -2

我的问题:接受任何整数并将其位置作为索引返回的函数的最优雅的实现是什么?

Assume I have a vector v with m elements in it, and a random access index to the vector called i.

When I increment the index, if it goes out of bounds, I want to index the first (zeroth) element. Similarly, when I decrement the index, if the index is < 0, I want to index to last element. At the moment I'm only moving through the container one element at a time, so came up with this function:

unsigned int GetIndexModM(int index,unsigned int m) {return (index + m) % m;}

The call-site might look like this:

std::vector<Whatever> v = ... // initialise with 5 elements
unsigned int i = 0;
unsigned int j = GetIndexModM(static_cast<int>(i) - 1,v.size()); // get preceeding index

This function will fail however if one subtracts a value > m from index:

unsigned int j = GetIndexModM(static_cast<int>(i) - 17,v.size()); // oops: returns -2

My question: What's the most elegant implementation of a function that takes any integer and returns it's place as an index?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦明 2024-12-02 10:10:48

处理 MOD 的技巧是这样的,它适用于正数和负数:

  val = ((val % mod_val) + mod_val) % mod_val; 

例如,假设我们希望将值保持在 0 到 359 之间(包括 0 和 359)。我们可以使用这个:

  val = ((val % 360) + 360) % 360; 

这是一个用 C++ 编写的简单示例。

int getmod(int val, int mod) {
  return ((val % mod) + mod) % mod; 
}

int main() {
  printf("%d\n", getmod(50,360));   // prints 50
  printf("%d\n", getmod(-400,360)); // prints 320
  printf("%d\n", getmod(350,360));  // prints 350
  printf("%d\n", getmod(375,360));  // prints 15
  printf("%d\n", getmod(-725,360));  // prints 355


  return 0;
}

The trick for handling MOD is this, which works with positive as well as negative numbers:

  val = ((val % mod_val) + mod_val) % mod_val; 

For example, assume we want to keep value between 0 and 359 inclusive. We could use this:

  val = ((val % 360) + 360) % 360; 

Here's a simple example in C++.

int getmod(int val, int mod) {
  return ((val % mod) + mod) % mod; 
}

int main() {
  printf("%d\n", getmod(50,360));   // prints 50
  printf("%d\n", getmod(-400,360)); // prints 320
  printf("%d\n", getmod(350,360));  // prints 350
  printf("%d\n", getmod(375,360));  // prints 15
  printf("%d\n", getmod(-725,360));  // prints 355


  return 0;
}
鸠书 2024-12-02 10:10:48

不幸的是,C++ 没有实现对于负整数仍然可以正确工作的正确模数。

我认为最干净的解决方案确实是使用 if 来正确处理所有情况。这至少使代码变得显而易见(因为每种情况都是显式)并且更容易发现错误:

unsigned GetIndexModM(int index, unsigned m) {
    if (index < 0)
        return GetIndexModM(index + m, m);
    if (index >= m)
        return index % m;
    return index;
}

Unfortunately, C++ doesn’t implement a proper modulus that still works correctly for negative integers.

I think the cleanest solution is indeed using if to take care of all cases properly. This at least makes the code obvious (because every case is explicit) and errors easier to find:

unsigned GetIndexModM(int index, unsigned m) {
    if (index < 0)
        return GetIndexModM(index + m, m);
    if (index >= m)
        return index % m;
    return index;
}
隱形的亼 2024-12-02 10:10:48

以下内容确保 index 位于 [0,n) 中,但只有一个模数运算且没有分支:

index = index % n + (index < 0)*n

其中第一项(包含模数运算符)将值获取到(-n,n) 和第二项确保该值在 [0,n) 中。

请注意,当 n 是无符号类型以及旧版(11 版之前)的 C++ 中时,这是不可靠的,其中 % 运算符对于负参数而言依赖于实现。

The following ensures that index is in [0,n) but with only one modulus operation and no branches:

index = index % n + (index < 0)*n

where the first term (containing the modulus operator) gets the value into (-n,n) and the second term ensures that the value is in [0,n).

Note that this is unreliable when n is an unsigned type and in older (pre-11) versions of C++ where the % operator is implementation dependent for negative arguments.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文