Linear interpolation of the Fibonacci sequence

Jelly, 5 bytes

_Ḟ1+¡

This is an iterative solution without built-ins. It uses the same indexing as the challenge spec.

Try it online!

Background

Let f be the function defined in the challenge spec and F the Fibonacci function defined as usual (i.e., with F(0) = 0). For a non-negative integer n, we have f(n) = F(n + 1). When 0 ≤ x < 1, the challenge spec defines f(n + x) as f(n) + (f(n + 1) - f(n))x.

Clearly, this just affects the base cases, but not the recursive formula, i.e., f(n) = f(n - 1) + f(n - 2) holds as it would for F. This means we can simplify the definition for non-integer arguments to the easier f(n) = f(n) + f(n - 1)x.

As others have noted in their answers, the recursive relationship also holds for non-integer arguments. This is easily verifiable, as

proof

Since f(0) = f(1) = 1, f in constant in the interval [0, 1] and f(0 + x) = 1 for all x. Furthermore, f(-1) = F(0) = 0, so f(-1 + x) = f(-1) + (f(0) - f(-1))x = 0 + 1x = x. These base cases cover in [-1, 1), so together with the recursive formula, they complete the definition of f.

How it works

As before, let n + x be the only argument of our monadic program.

¡ is a quick, meaning that it consumes some links to its left and turns them into a quicklink. ¡ in particular consumes either one or two links.

  • <F:monad|dyad><N:any> calls the link N, returning r, and executes F a total of r times.

  • <nilad|missing><F:monad|dyad> sets r to the last command-line argument (or an input from STDIN in their absence) and executes F a total of r times.

Since 1 is a nilad (a link without arguments), the second case applies, and will execute + n times (a non-integer argument is rounded down). After each call to +, the left argument of the quicklink is replaced with the return value, and the right argument with the previous value of the left argument.

As for the entire program, floors the input, yielding n; then _ subtract the result from the input, yielding **x, which becomes the return value.

1+¡ then calls – as described before – with left argument 1 = f(0 + x) and right argument x = f(-1 + x), which computes the desired output.


Mathematica, 32 bytes

If[#<2,1~Max~#,#0[#-1]+#0[#-2]]&

Pure function taking a nonnegative real number as input and returning a real number. If 1~Max~# were replaced by 1, this would be the standard recursive definition of the 0-indexed Fibonacci numbers for integer arguments. But 1~Max~# is the correct piecewise linear function for real inputs between 0 and 2, and the recursion takes care of the rest. (Trivia fact: changing this to the 1-indexed Fibonacci numbers can be accomplished simply by changing the Max to a Min!)

The shortest I could get with the builtin is the 37-byte (b=Fibonacci)[i=Floor@#](#-i)+b[i+1]&.


JavaScript (ES6), 30 bytes

f=x=>x<1?1:x<2?x:f(x-1)+f(x-2)
<input type=number value=2.4 oninput="O.value=f(value)"> <input id=O value=2.4 disabled>

Trivial modification of the zero-indexed recursive Fibonacci sequence definition. May give slight rounding errors for some inputs.