2
\$\begingroup\$

I was writing a simple function that would return the Fibonacci sequence up to the nth term and for whatever reason started wasting a lot of time on it. Here's what I came up with:

static IEnumerable<int> Fibonacci(int n)
{
 int last = 0, 
 oneBefore = 0;
 if (n > 0) yield return oneBefore = 0;
 if (n > 1) yield return last = 1;
 if (n > 2)
 {
 while (n-- - 2 > 0)
 {
 yield return last = oneBefore + (oneBefore = last);
 }
 }
}

This is pretty close to what I want, but it has those three ugly if branches at the top level. Initially, I was trying to do something like this for the 0 and 1 case:

yield return (new[] { 0, 1 }).Take(n);

So that it would nicely handle cases where n was 0, 1 or greater. Unfortunately C# doesn't allow mixing of returning complete enumerables with yield statements, so that didn't work.

So here are my questions for what I want to improve:

  • Is there a way I can avoid the if branches there and somehow elegantly and concisely deal with both degenerate cases?
  • Is there a way I can avoid having that variable initialization statement at the beginning of the function, or even better, avoid having to keep the two variables at all?
asked May 8, 2015 at 5:27
\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

Consider breaking it up into two methods: one, Fibonacci(), that represents the infinite* Fibonacci sequence, and another, Fibonacci(int), that just returns Fibonacci().Take(n). This removes the branching.

An implementation might look like this:

static IEnumerable<int> Fibonacci(int n)
{
 return Fibonacci().Take(n);
}
static IEnumerable<int> Fibonacci()
{
 int a = 0;
 int b = 1;
 while (true)
 {
 yield return a;
 int c = a + b;
 a = b;
 b = c;
 }
}

* Well, the first 47 values that fit in an int.

answered May 8, 2015 at 7:04
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.