82 lines
8.7 KiB
Markdown
82 lines
8.7 KiB
Markdown
![]() |
# Function
|
||
|
|
||
|
Function is a very basic term in [mathematics](math.md) and [programming](programming.md) with a slightly different meanings in each: mathematical function maps numbers to other numbers, a function in programming is a subprograms to which we divide a bigger program. Well, that's pretty simplified but those are the basic ideas. A more detailed explanation will follow.
|
||
|
|
||
|
## Mathematical Functions
|
||
|
|
||
|
In mathematics functions can be defined and viewed from different angles but a function is basically anything that assigns each member of some set *A* (so called *domain*) exactly one member of a potentially different set *B* (so called *codomain*). A typical example of a function is an equation that from one "input number" computes another number, for example:
|
||
|
|
||
|
*f(x) = x / 2*
|
||
|
|
||
|
Here we call the function *f* and say it takes one [parameter](parameter.md) (the "input number") called *x*. The "output number" is defined by the right side of the equation, *x / 2*, i.e. the number output by the function will be half of the parameter (*x*). The domain of this function (the set of all possible numbers that can be taken as input) is the set of [real numbers](real_number.md) and the codomain is also the set of real numbers. This equation assigns each real number *x* another real number *x / 2*, therefore it is a function.
|
||
|
|
||
|
{ I always imagined functions as kind of little boxes into which we throw a number and another number falls out. ~drummyfish }
|
||
|
|
||
|
Now consider a function *f2(x) = 1 - 1 / x*. Note that in this case the domain is the set of real number minus [zero](zero.md); the function can't take zero as an input because we can't divide by zero. The codomain is the set of real numbers minus one because we can't ever get one as a result.
|
||
|
|
||
|
Another common example of a function is the [sine](sin.md) function that we write as *sin(x)*. It can be defined in several ways, commonly e.g. as follows: considering a [right triangle](right_triangle.md) with one of its angles equal to *x* [radians](radian.md), *sin(x)* is equal to the ratio of the side opposing this angle to the triangle [hypotenuse](hypotenuse.md). For example *sin(pi / 2) = sin(45 degrees) = 1 / sqrt(2) ~= 0.71*. The domain of sine function is again the set of real number but its codomain is only the set of real numbers between 0 and 1 because the ratio of said triangle sides can never be negative or greater than 1, i.e. sine function will never yield a number outside the interval <0,1>.
|
||
|
|
||
|
Note that these functions have to satisfy a few conditions to really be functions. Firstly each number from the domain must be assigned exactly one number (although this can be "cheated" by e.g. using a set of couples as a codomain), even though multiple input numbers can give the same result number. Also importantly **the function result must only depend on the function's parameter**, i.e. the function mustn't have any memory or inside state and it mustn't depend on any external factors (such as current time) or use any randomness (such as a dice roll) in its calculation. For a certain [argument](argument.md) (input number) a function must give the same result every time. For this reason not everything that transforms numbers to other numbers can be considered a function.
|
||
|
|
||
|
Functions can have multiple parameters, for example:
|
||
|
|
||
|
*g(x,y) = (x + y) / 2*
|
||
|
|
||
|
The function *g* computes the average of its two parameters, *x* and *y*. Formally we can see this as a function that maps elements from a set of couples of real numbers to the set of real numbers.
|
||
|
|
||
|
Of course function may also work with just [whole numbers](whole_number.md), also [complex numbers](complex_number.md), [quaternions](quaternion.md) and theoretically just anything crazy like e.g. the set of animals :) However in these "weird" cases we generally no longer use the word *function* but rather something like a *[map](map.md)*. In mathematical terminology we may hear things such as a *real function of a complex parameter* which means a function that takes a complex number as an input and gives a real number result.
|
||
|
|
||
|
To get better overview of a certain function we may try to represent it graphically, most commonly we make function **[plots](plot.md)** also called **graphs**. For a function of a single parameter we draw graphs onto a grid where the horizontal axis represents number line of the parameter (input) and the vertical axis represents the result. For example plotting a function *f(x) = ((x - 1) / 4)^2 + 0.8* may look like this:
|
||
|
|
||
|
```
|
||
|
|
||
|
|f(x)
|
||
|
2+
|
||
|
'.._ |
|
||
|
''--1+.____...--'
|
||
|
___,__,__|__,__,_____x
|
||
|
-2 -1 |0 1 2
|
||
|
-1+
|
||
|
|
|
||
|
-2+
|
||
|
|
|
||
|
|
||
|
|
||
|
```
|
||
|
|
||
|
This is of course done by plotting various points [*x*,*f(x)*] and connecting them by a line.
|
||
|
|
||
|
Plotting functions of multiple parameters is more difficult because we need more axes and get to higher [dimensions](dimension.md). For functions of 2 parameters we can draw e.g. a [heightmap](heightmap.md) or create a [3D model](3d_model.md) of the surface which the function defines. 3D functions may in theory be displayed like 2D functions with added time dimension (animated) or as 3D density clouds. For higher dimensions we usually resort to some kind of cross-section or [projection](projection.md) to lower dimensions.
|
||
|
|
||
|
Functions can have certain properties such as:
|
||
|
|
||
|
- being **[bijective](bijection.md)**: A bijective function pairs exactly one element from the domain with one element from codomain and vice versa, i.e. for every result (element of codomain) of the function it is possible to unambiguously say which input created it. For bijective functions we can create **[inverse functions](inverse_function.md)** that reverse the mapping (e.g. [arcus sine](asin.md) is the inverse of a [sin](sin.md) function that's limited to the interval where it is bijective). For example *f(x) = 2 * x* is bijective with its inverse function being *f^(-1)(x) = x / 2*, but *f2(x) = x^2* is not bijective because e.g. both 1 and -1 give the result of 1.
|
||
|
- being an **[even function](even_function.md)**: For this function it holds that *f(x) = f(-x)*, i.e. the plotted function is symmetric by the vertical axis. Example is the [cosine](cos.md) function.
|
||
|
- being an **[odd function](odd_function.md)**: For this function it holds that *-f(x) = f(-x)*, i.e. the plotted function is symmetric by the center point [0,0]. Example is the [sine](sin.md) function.
|
||
|
|
||
|
In context of functions we may encounter the term [composition](composition.md) which simply means chaining the functions. E.g. the composition of functions *f(x)* and *g(x)* is written as *(f o g)(x)* which is the same as *f(g(x))*.
|
||
|
|
||
|
[Calculus](calculus.md) is an important mathematical field that studies changes of continuous functions. It can tell us how quickly functions grow, where they have maximum and minimum values, what's the area under the line in their plot and many other things.
|
||
|
|
||
|
## Programming Functions
|
||
|
|
||
|
In programming the definition of a function is less strict, even though some languages, namely [functional](functional.md) ones, are built around purely mathematical functions -- for distinction we call these strictly mathematical functions **pure**. In traditional languages functions may or may not be pure, a function here normally means a **subprogram** which can take parameters and return a value, just as a mathematical function, but it can further break some of the rules of mathematical functions -- for example it may have so called **[side effects](side_effect.md)**, i.e. performing additional actions besides just returning a number (such as modifying data in memory, printing something to the screen etc.), or use randomness and internal states, i.e. potentially returning different numbers when invoked (called) multiple times with exactly the same parameters. These functions are called **impure**; in programming a *function* without an adjective is implicitly expected to be impure. Thanks to allowing side effects these functions don't have to actually return any value, their purpose may be to just invoke some behavior such as writing something to the screen, initializing some hardware etc. The following piece of code demonstrates this in [C](c.md):
|
||
|
|
||
|
```
|
||
|
int max(int a, int b, int c) // pure function
|
||
|
{
|
||
|
return (a > b) ? (a > c ? a : c) : (b > c ? b : c);
|
||
|
}
|
||
|
|
||
|
unsigned int lastPresudorandomValue = 0;
|
||
|
|
||
|
unsigned int pseudoRandom(unsigned int maxValue) // impure function
|
||
|
{
|
||
|
lastPresudorandomValue = // side effect: working with global variable
|
||
|
lastPresudorandomValue * 7907 + 7;
|
||
|
|
||
|
return (lastPresudorandomValue >> 2) % (maxValue + 1);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
In older languages functions were also called *[procedures](procedure.md)* or *[routines](routine.md)*. Sometimes there was some distinction between them, e.g. in [Pascal](pascal.md) functions returned a value while procedures didn't.
|