我们如何在没有条件的情况下递增然后递减计数器?

Posted

技术标签:

【中文标题】我们如何在没有条件的情况下递增然后递减计数器?【英文标题】:How can we increment and then decrement a counter without conditionals? 【发布时间】:2014-12-22 19:44:48 【问题描述】:

我正在寻找一种巧妙的方法来增加然后减少计数器变量。我希望计数器变量以较低的值开始并递增,向更高的值。一旦达到较高的值,计数器就会递减,直到回到较低的值。一旦达到较低的值,计数器就会再次增加到较高的值......我想你明白了。

我正在处理canvas animation,我想在其中使用一些聪明才智,而不使用if 或其他条件测试:

这里是处理计数器变量的条件逻辑:

incrementing = true

foo = ->

    length += 1 if incrementing
    length -= 1 if not incrementing

    incrementing = false if length > 100
    incrementing = true  if length < 1

最初,我认为我可以使用模数。但是,模除法只会将计数器重置回较低的值——一旦达到最大值,它不会递减计数器。

 0 % 10 =  0
 1 % 10 =  1
 2 % 10 =  2
 3 % 10 =  3
 4 % 10 =  4
 5 % 10 =  5
 6 % 10 =  6
 7 % 10 =  7
 8 % 10 =  8
 9 % 10 =  9
10 % 10 =  0
11 % 10 =  1
12 % 10 =  2
13 % 10 =  3

我确信必须有一种方法可以在不使用条件测试的情况下做到这一点。假设底部值为 0,顶部值为 10,则该方法应输出以下内容。

? =  0
? =  1
? =  2
? =  3
? =  4
? =  5
? =  6
? =  7
? =  8
? =  9
? =  8
? =  7
? =  6
? =  5

【问题讨论】:

+1 需要一个完全非问题的解决方案,纯粹是为了让你的代码更漂亮。这就是我们学习 CoffeeScript 的原因。 【参考方案1】:

首先让我们看一些波浪!

你好挥手!

您能找出符合您需求的那一款吗?

如果你猜对了Triangle Wave,那你就猜对了!

三角波以均匀斜率振荡,直到达到最小值或最大值,然后斜率反转。

这里需要解决两件事:

函数的起点将从波浪的中间开始 波从x 振荡到-x

我们希望从0 开始输出,并且只包含正值

function triangle(t, a) 
  return Math.abs(((t + a/2) % a) - a/2);

我们来试试吧

for (var i=0; i<20; i++) 
  console.log(i, triangle(i, 10));

输出

0 0
1 1
2 2
3 3
4 4
5 5
6 4
7 3
8 2
9 1
10 0
11 1
12 2
13 3
14 4
15 5
16 4
17 3
18 2
19 1

所以当我们调用triangle(i, 10) 时,10 就是“句号”。这告诉我们在函数重复之前我们希望在函数中执行多少步。

6 的句点会给我们 6 个值,0, 1, 2, 3, 2, 1

4 的句点会给我们 4 个值,0, 1, 2, 1

如果你想从0-9出发,你需要一段20

【讨论】:

这里是锯齿版本。用于重置回 0 function sawtooth(t, a) return Math.abs(((t + a) % a)); 【参考方案2】:

这是一个:

(x&8)+(x&7)*((~x&8)/4-1)

这会给你

0,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1,0,1,...

当然里面实际上有一个条件,只是隐藏为按位运算。

另一种可能性是三角波计数器:

(x^((x&8)/-8))&7

会的

0,1,2,3,4,5,6,7,7,6,5,4,3,2,1,0,0,...

还有一个隐藏的条件,它会在中途翻转位。

【讨论】:

以上是关于我们如何在没有条件的情况下递增然后递减计数器?的主要内容,如果未能解决你的问题,请参考以下文章

什么会导致for循环在它应该递增时递减?

shared_ptrs 是不是由于引用计数器原子递增/递减而遇到缓存未命中?

基于具有序列的条件递增计数器

最高并行事件时间

在啥情况下(如果有),C 中前缀和后缀递增/递减运算符之间的性能是不是存在差异? [复制]

如何从活动中调用片段方法?