最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can we increment and then decrement a counter without conditionals? - Stack Overflow

programmeradmin1浏览0评论

I'm looking for a clever way to increment and then decrement a counter variable. I want the counter variable to begin at a low value and increment, towards a higher value. Once it reaches the higher value, the counter decrements until it reaches back to the lower value. Once it reaches the lower value, the counter increments again to the higher value ... I think you get the point.

I am working on a a canvas animation where I'd like to employ some cleverness, without using if or other conditional tests:

Here is the conditional logic that handles the counter variable:

incrementing = true

foo = ->

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

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

Initially, I thought I could use modulo. However, modulo division only resets the counter back to the lower value -- it doesn't decrement the counter once it reaches the top value.

 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

I'm sure there has to be a way to do this without using conditional tests. Assuming a bottom value of 0 and a top value of 10, the method should output the following.

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

I'm looking for a clever way to increment and then decrement a counter variable. I want the counter variable to begin at a low value and increment, towards a higher value. Once it reaches the higher value, the counter decrements until it reaches back to the lower value. Once it reaches the lower value, the counter increments again to the higher value ... I think you get the point.

I am working on a a canvas animation where I'd like to employ some cleverness, without using if or other conditional tests:

Here is the conditional logic that handles the counter variable:

incrementing = true

foo = ->

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

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

Initially, I thought I could use modulo. However, modulo division only resets the counter back to the lower value -- it doesn't decrement the counter once it reaches the top value.

 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

I'm sure there has to be a way to do this without using conditional tests. Assuming a bottom value of 0 and a top value of 10, the method should output the following.

? =  0
? =  1
? =  2
? =  3
? =  4
? =  5
? =  6
? =  7
? =  8
? =  9
? =  8
? =  7
? =  6
? =  5
Share Improve this question edited Oct 27, 2014 at 15:27 luk3thomas asked Oct 27, 2014 at 15:16 luk3thomasluk3thomas 2,6221 gold badge19 silver badges20 bronze badges 1
  • 1 +1 for a needing a solution to a total non-problem, purely to make your code more beautiful. This is why we learn CoffeeScript. – Carl Younger Commented Oct 29, 2014 at 15:42
Add a ment  | 

2 Answers 2

Reset to default 16

First let's look at some waves !

Hello waves !

Can you identify the one that matches your needs ?

If you guessed Triangle Wave, you're right !

Triangle wave oscillates with a uniform slope until it hits a min or max, and then the slope is inverted.

Two things to work out here:

  • the origin of the function will start in the middle of the wave
  • the wave oscillates from x to -x

We want to start the output at 0 and only include positive values

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

Let's try it out

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

Output

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

So when we call triangle(i, 10) the 10 is the "period". This tells us how many steps we want to have in our function before it repeats.

A period of 6 would give us 6 values, 0, 1, 2, 3, 2, 1

A period of 4 would give us 4 values, 0, 1, 2, 1 etc

If you want to go from 0-9, you would need a period of 20

Here's one:

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

which will give you

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

Of course there actually is a conditional in there, just hidden as a bitwise operation.

Another possibility is a triangle wave counter:

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

which does

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

again there's a hidden conditional that flips the bits when it gets halfway.

发布评论

评论列表(0)

  1. 暂无评论