Articles

5.4: Logarithmic Functions


Learning Objectives

  • Convert from logarithmic to exponential form.
  • Convert from exponential to logarithmic form.
  • Evaluate logarithms.
  • Use common logarithms.
  • Use natural logarithms.

In 2010, a major earthquake struck Haiti, destroying or damaging over 285,000 homes. One year later, another, stronger earthquake devastated Honshu, Japan, destroying or damaging over 332,000 buildings,like those shown in Figure (PageIndex{1}). Even though both caused substantial damage, the earthquake in 2011 was 100 times stronger than the earthquake in Haiti. How do we know? The magnitudes of earthquakes are measured on a scale known as the Richter Scale. The Haitian earthquake registered a 7.0 on the Richter Scalewhereas the Japanese earthquake registered a 9.0.

The Richter Scale is a base-ten logarithmic scale. In other words, an earthquake of magnitude (8) is not twice as great as an earthquake of magnitude (4). It is

[10^{8−4}=10^4=10,000 onumber]

times as great! In this lesson, we will investigate the nature of the Richter Scale and the base-ten function upon which it depends.

Converting from Logarithmic to Exponential Form

In order to analyze the magnitude of earthquakes or compare the magnitudes of two different earthquakes, we need to be able to convert between logarithmic and exponential form. For example, suppose the amount of energy released from one earthquake were 500 times greater than the amount of energy released from another. We want to calculate the difference in magnitude. The equation that represents this problem is (10^x=500), where (x) represents the difference in magnitudes on the Richter Scale. How would we solve for (x)?

We have not yet learned a method for solving exponential equations. None of the algebraic tools discussed so far is sufficient to solve (10^x=500). We know that ({10}^2=100) and ({10}^3=1000), so it is clear that (x) must be some value between 2 and 3, since (y={10}^x) is increasing. We can examine a graph, as in Figure (PageIndex{1}), to better estimate the solution.

Estimating from a graph, however, is imprecise. To find an algebraic solution, we must introduce a new function. Observe that the graph in Figure (PageIndex{2}) passes the horizontal line test. The exponential function (y=b^x) is one-to-one, so its inverse, (x=b^y) is also a function. As is the case with all inverse functions, we simply interchange (x) and (y) and solve for (y) to find the inverse function. To represent (y) as a function of (x), we use a logarithmic function of the form (y={log}_b(x)). The base (b) logarithm of a number is the exponent by which we must raise (b) to get that number.

We read a logarithmic expression as, “The logarithm with base (b) of (x) is equal to (y),” or, simplified, “log base (b) of (x) is (y).” We can also say, “(b) raised to the power of (y) is (x),” because logs are exponents. For example, the base (2) logarithm of (32) is (5), because (5) is the exponent we must apply to (2) to get (32). Since (2^5=32), we can write ({log}_232=5). We read this as “log base (2) of (32) is (5).”

We can express the relationship between logarithmic form and its corresponding exponential form as follows:

[egin{align} log_b(x)=yLeftrightarrow b^y=x, b> 0, b eq 1 end{align}]

Note that the base (b) is always positive.

Because logarithm is a function, it is most correctly written as (log_b(x)), using parentheses to denote function evaluation, just as we would with (f(x)). However, when the input is a single variable or number, it is common to see the parentheses dropped and the expression written without parentheses, as (log_bx). Note that many calculators require parentheses around the (x).

We can illustrate the notation of logarithms as follows:

Notice that, comparing the logarithm function and the exponential function, the input and the output are switched. This means (y=log_b(x)) and (y=b^x) are inverse functions.

DEFINITION OF THE LOGARITHMIC FUNCTION

A logarithm base (b) of a positive number (x) satisfies the following definition.

For (x>0), (b>0), (b≠1),

[egin{align} y={log}_b(x) ext{ is equivalent to } b^y=x end{align}]

where,

  • we read ({log}_b(x)) as, “the logarithm with base (b) of (x)” or the “log base (b) of (x)."
  • the logarithm (y) is the exponent to which (b) must be raised to get (x).

Also, since the logarithmic and exponential functions switch the (x) and (y) values, the domain and range of the exponential function are interchanged for the logarithmic function. Therefore,

  • the domain of the logarithm function with base (b) is ((0,infty)).
  • the range of the logarithm function with base (b) is ((−infty,infty)).

Q&A: Can we take the logarithm of a negative number?

No. Because the base of an exponential function is always positive, no power of that base can ever be negative. We can never take the logarithm of a negative number. Also, we cannot take the logarithm of zero. Calculators may output a log of a negative number when in complex mode, but the log of a negative number is not a real number.

How to: Given an equation in logarithmic form ({log}_b(x)=y), convert it to exponential form

  1. Examine the equation (y={log}_bx) and identify (b), (y),and (x).
  2. Rewrite ({log}_bx=y) as (b^y=x).

Example (PageIndex{1}): Converting from Logarithmic Form to Exponential Form​​​​​​

Write the following logarithmic equations in exponential form.

  1. ({log}_6(sqrt{6})=dfrac{1}{2})
  2. ({log}_3(9)=2)

Solution

First, identify the values of (b), (y),and (x). Then, write the equation in the form (b^y=x).

  1. ({log}_6(sqrt{6})=dfrac{1}{2})

    Here, (b=6), (y=dfrac{1}{2}),and (x=sqrt{6}). Therefore, the equation ({log}_6(sqrt{6})=dfrac{1}{2}) is equivalent to

    (6^{ frac{1}{2}}=sqrt{6})

  2. ({log}_3(9)=2)

    Here, (b=3), (y=2),and (x=9). Therefore, the equation ({log}_3(9)=2) is equivalent to

(3^2=9)

Exercise (PageIndex{1})

Write the following logarithmic equations in exponential form.

  1. ({log}_{10}(1,000,000)=6)
  2. ({log}_5(25)=2)
Answer a

({log}_{10}(1,000,000)=6) is equivalent to ({10}^6=1,000,000)

Answer b

({log}_5(25)=2) is equivalent to (5^2=25)

Converting from Exponential to Logarithmic Form

To convert from exponents to logarithms, we follow the same steps in reverse. We identify the base (b),exponent (x),and output (y). Then we write (x={log}_b(y)).

Example (PageIndex{2}): Converting from Exponential Form to Logarithmic Form

Write the following exponential equations in logarithmic form.

  1. (2^3=8)
  2. (5^2=25)
  3. ({10}^{−4}=dfrac{1}{10,000})

Solution

First, identify the values of (b), (y),and (x). Then, write the equation in the form (x={log}_b(y)).

  1. (2^3=8)

    Here, (b=2), (x=3),and (y=8). Therefore, the equation (2^3=8) is equivalent to ({log}_2(8)=3).

  2. (5^2=25)

    Here, (b=5), (x=2),and (y=25). Therefore, the equation (5^2=25) is equivalent to ({log}_5(25)=2).

  3. ({10}^{−4}=dfrac{1}{10,000})

    Here, (b=10), (x=−4),and (y=dfrac{1}{10,000}). Therefore, the equation ({10}^{−4}=dfrac{1}{10,000}) is equivalent to ({log}_{10} left (dfrac{1}{10,000} ight )=−4).

Exercise (PageIndex{2})

Write the following exponential equations in logarithmic form.

  1. (3^2=9)
  2. (5^3=125)
  3. (2^{−1}=dfrac{1}{2})
Answer a

(3^2=9) is equivalent to ({log}_3(9)=2)

Answer b

(5^3=125) is equivalent to ({log}_5(125)=3)

Answer c

(2^{−1}=dfrac{1}{2}) is equivalent to ({log}_2 left (dfrac{1}{2} ight )=−1)

Evaluating Logarithms

Knowing the squares, cubes, and roots of numbers allows us to evaluate many logarithms mentally. For example, consider ({log}_28). We ask, “To what exponent must (2) be raised in order to get 8?” Because we already know (2^3=8), it follows that ({log}_28=3).

Now consider solving ({log}_749) and ({log}_327) mentally.

  • We ask, “To what exponent must (7) be raised in order to get (49)?” We know (7^2=49). Therefore, ({log}_749=2)
  • We ask, “To what exponent must (3) be raised in order to get (27)?” We know (3^3=27). Therefore, (log_{3}27=3)

Even some seemingly more complicated logarithms can be evaluated without a calculator. For example, let’s evaluate (log_{ce{2/3}} frac{4}{9}) mentally.

  • We ask, “To what exponent must (ce{2/3}) be raised in order to get (ce{4/9})? ” We know (2^2=4) and (3^2=9), so [{left(dfrac{2}{3} ight )}^2=dfrac{4}{9}. onumber] Therefore, [{log}_{ce{2/3}} left (dfrac{4}{9} ight )=2. onumber]

How to: Given a logarithm of the form (y={log}_b(x)),evaluate it mentally

  1. Rewrite the argument (x) as a power of (b): (b^y=x).
  2. Use previous knowledge of powers of (b) identify (y) by asking, “To what exponent should (b) be raised in order to get (x)?”

Example (PageIndex{3}): Solving Logarithms Mentally

Solve (y={log}_4(64)) without using a calculator.

Solution

First we rewrite the logarithm in exponential form: (4^y=64). Next, we ask, “To what exponent must (4) be raised in order to get (64)?”

We know

(4^3=64)

Therefore,

({log}_4(64)=3)

Exercise (PageIndex{3})

Solve (y={log}_{121}(11)) without using a calculator.

Answer

({log}_{121}(11)=dfrac{1}{2}) (recalling that (sqrt{121}={(121)}^{ frac{1}{2}}=11))

Example (PageIndex{4}): Evaluating the Logarithm of a Reciprocal

Evaluate (y={log}_3 left (dfrac{1}{27} ight )) without using a calculator.

Solution

First we rewrite the logarithm in exponential form: (3^y=dfrac{1}{27}). Next, we ask, “To what exponent must (3) be raised in order to get (dfrac{1}{27})?”

We know (3^3=27),but what must we do to get the reciprocal, (dfrac{1}{27})? Recall from working with exponents that (b^{−a}=dfrac{1}{b^a}). We use this information to write

[egin{align*} 3^{-3}&= dfrac{1}{3^3} &= dfrac{1}{27} end{align*}]

Therefore, ({log}_3 left (dfrac{1}{27} ight )=−3).

Exercise (PageIndex{4})

Evaluate (y={log}_2 left (dfrac{1}{32} ight )) without using a calculator.

Answer

({log}_2 left (dfrac{1}{32} ight )=−5)

Using Common Logarithms

Sometimes we may see a logarithm written without a base. In this case, we assume that the base is (10). In other words, the expression (log(x)) means ({log}_{10}(x)). We call a base (-10) logarithm a common logarithm. Common logarithms are used to measure the Richter Scale mentioned at the beginning of the section. Scales for measuring the brightness of stars and the pH of acids and bases also use common logarithms.

DEFINITION OF THE COMMON LOGARITHM

A common logarithm is a logarithm with base (10). We write ({log}_{10}(x)) simply as (log(x)). The common logarithm of a positive number (x) satisfies the following definition.

For (x>0),

[egin{align} y={log}(x) ext{ is equivalent to } {10}^y=x end{align}]

We read (log(x)) as, “the logarithm with base (10) of (x) ” or “log base (10) of (x).”

The logarithm (y) is the exponent to which (10) must be raised to get (x).

How to: Given a common logarithm of the form (y=log(x)), evaluate it mentally

  1. Rewrite the argument (x) as a power of (10): ({10}^y=x).
  2. Use previous knowledge of powers of (10) to identify (y) by asking, “To what exponent must (10) be raised in order to get (x)?”

Example (PageIndex{5}): Finding the Value of a Common Logarithm Mentally

Evaluate (y=log(1000)) without using a calculator.

Solution

First we rewrite the logarithm in exponential form: ({10}^y=1000). Next, we ask, “To what exponent must (10) be raised in order to get (1000)?” We know

({10}^3=1000)

Therefore, (log(1000)=3).

Exercise (PageIndex{5})

Evaluate (y=log(1,000,000)).

Answer

(log(1,000,000)=6)

How to: Given a common logarithm with the form (y=log(x)),evaluate it using a calculator

  1. Press [LOG].
  2. Enter the value given for (x),followed by [ ) ].
  3. Press [ENTER].

Example (PageIndex{6}): ​​​​​​Finding the Value of a Common Logarithm Using a Calculator

Evaluate (y=log(321)) to four decimal places using a calculator.

Solution

  • Press [LOG].
  • Enter 321, followed by [ ) ].
  • Press [ENTER].

Rounding to four decimal places, (log(321)≈2.5065).

Analysis

Note that ({10}^2=100) and that ({10}^3=1000). Since (321) is between (100) and (1000), we know that (log(321)) must be between (log(100)) and (log(1000)). This gives us the following:

(100<321<1000)

(2<2.5065<3)

Exercise (PageIndex{6})

Evaluate (y=log(123)) to four decimal places using a calculator.

Answer

(log(123)≈2.0899)

Example (PageIndex{7}): Rewriting and Solving a Real-World Exponential Model

The amount of energy released from one earthquake was (500) times greater than the amount of energy released from another. The equation ({10}^x=500) represents this situation, where (x) is the difference in magnitudes on the Richter Scale. To the nearest thousandth, what was the difference in magnitudes?

Solution

We begin by rewriting the exponential equation in logarithmic form.

({10}^x=500)

(log(500)=x) Use the definition of the common log.

Next we evaluate the logarithm using a calculator:

  • Press [LOG].
  • Enter (500),followed by [ ) ].
  • Press [ENTER].
  • To the nearest thousandth, (log(500)≈2.699).

The difference in magnitudes was about (2.699).

Exercise (PageIndex{7})

​​​​The amount of energy released from one earthquake was (8,500) times greater than the amount of energy released from another. The equation ({10}^x=8500) represents this situation, where (x) is the difference in magnitudes on the Richter Scale. To the nearest thousandth, what was the difference in magnitudes?

Answer

The difference in magnitudes was about (3.929).

Using Natural Logarithms

The most frequently used base for logarithms is (e). Base (e) logarithms are important in calculus and some scientific applications; they are called natural logarithms. The base (e) logarithm, ({log}_e(x)), has its own notation,(ln(x)). Most values of (ln(x)) can be found only using a calculator. The major exception is that, because the logarithm of (1) is always (0) in any base, (ln1=0). For other natural logarithms, we can use the (ln) key that can be found on most scientific calculators. We can also find the natural logarithm of any power of (e) using the inverse property of logarithms.

DEFINITION OF THE NATURAL LOGARITHM

A natural logarithm is a logarithm with base (e). We write ({log}_e(x)) simply as (ln(x)). The natural logarithm of a positive number (x) satisfies the following definition.

For (x>0),

(y=ln(x)) is equivalent to (e^y=x)

We read (ln(x)) as, “the logarithm with base (e) of (x)” or “the natural logarithm of (x).”

The logarithm (y) is the exponent to which (e) must be raised to get (x).

Since the functions (y=e^x) and (y=ln(x)) are inverse functions, (ln(e^x)=x) for all (x) and (e^{ln (x)}=x) for (x>0).

How to: Given a natural logarithm with the form (y=ln(x)), evaluate it using a calculator

  1. Press [LN].
  2. Enter the value given for (x), followed by [ ) ].
  3. Press [ENTER].

Example (PageIndex{8}): Evaluating a Natural Logarithm Using a Calculator

Evaluate (y=ln(500)) to four decimal places using a calculator.

Solution

  • Press [LN].
  • Enter (500),followed by [ ) ].
  • Press [ENTER].

Rounding to four decimal places, (ln(500)≈6.2146)

Exercise (PageIndex{8})

Evaluate (ln(−500)).

Answer

It is not possible to take the logarithm of a negative number in the set of real numbers.

Media

Access this online resource for additional instruction and practice with logarithms.

  • Introduction to Logarithms

Key Equations

Definition of the logarithmic functionFor (x>0), (b>0), (b≠1), (y={log}_b(x)) if and only if (b^y=x).
Definition of the common logarithmFor (x>0), (y=log(x)) if and only if ({10}^y=x).
Definition of the natural logarithmFor (x>0), (y=ln(x)) if and only if (e^y=x).

Key Concepts

  • The inverse of an exponential function is a logarithmic function, and the inverse of a logarithmic function is an exponential function.
  • Logarithmic equations can be written in an equivalent exponential form, using the definition of a logarithm. See Example (PageIndex{1}).
  • Exponential equations can be written in their equivalent logarithmic form using the definition of a logarithm See Example (PageIndex{2}).
  • Logarithmic functions with base (b) can be evaluated mentally using previous knowledge of powers of (b). See Example (PageIndex{3}) and Example (PageIndex{4}).
  • Common logarithms can be evaluated mentally using previous knowledge of powers of (10). See Example (PageIndex{5}).
  • When common logarithms cannot be evaluated mentally, a calculator can be used. See Example (PageIndex{6}).
  • Real-world exponential problems with base (10) can be rewritten as a common logarithm and then evaluated using a calculator. See Example (PageIndex{7}).
  • Natural logarithms can be evaluated using a calculator Example (PageIndex{8}).

Graphing Logarithmic Functions [5.4] 2. Given f(x) = 4(2)*. a. Find f'(x). Note: Your function should be a single logarithm so use the change of base formula if needed.

help_outline

Image Transcriptionclose

Graphing Logarithmic Functions [5.4] 2. Given f(x) = 4(2)*. a. Find f'(x). Note: Your function should be a single logarithm so use the change of base formula if needed.


Lua is a dynamically typed language. This means that variables do not have types only values do. There are no type definitions in the language. All values carry their own type.

All values in Lua are first-class values. This means that all values can be stored in variables, passed as arguments to other functions, and returned as results.

There are eight basic types in Lua: nil, boolean, number, string, function, userdata, thread, and table. The type nil has one single value, nil, whose main property is to be different from any other value it often represents the absence of a useful value. The type boolean has two values, false and true. Both nil and false make a condition false they are collectively called false values. Any other value makes a condition true. Despite its name, false is frequently used as an alternative to nil, with the key difference that false behaves like a regular value in a table, while a nil in a table represents an absent key.

The type number represents both integer numbers and real (floating-point) numbers, using two subtypes: integer and float. Standard Lua uses 64-bit integers and double-precision (64-bit) floats, but you can also compile Lua so that it uses 32-bit integers and/or single-precision (32-bit) floats. The option with 32 bits for both integers and floats is particularly attractive for small machines and embedded systems. (See macro LUA_32BITS in file luaconf.h .)

Unless stated otherwise, any overflow when manipulating integer values wrap around, according to the usual rules of two-complement arithmetic. (In other words, the actual result is the unique representable integer that is equal modulo 2 n to the mathematical result, where n is the number of bits of the integer type.)

Lua has explicit rules about when each subtype is used, but it also converts between them automatically as needed (see §3.4.3). Therefore, the programmer may choose to mostly ignore the difference between integers and floats or to assume complete control over the representation of each number.

The type string represents immutable sequences of bytes. Lua is 8-bit clean: strings can contain any 8-bit value, including embedded zeros (' '). Lua is also encoding-agnostic it makes no assumptions about the contents of a string. The length of any string in Lua must fit in a Lua integer.

Lua can call (and manipulate) functions written in Lua and functions written in C (see §3.4.10). Both are represented by the type function.

The type userdata is provided to allow arbitrary C data to be stored in Lua variables. A userdata value represents a block of raw memory. There are two kinds of userdata: full userdata, which is an object with a block of memory managed by Lua, and light userdata, which is simply a C pointer value. Userdata has no predefined operations in Lua, except assignment and identity test. By using metatables, the programmer can define operations for full userdata values (see §2.4). Userdata values cannot be created or modified in Lua, only through the C API. This guarantees the integrity of data owned by the host program and C libraries.

The type thread represents independent threads of execution and it is used to implement coroutines (see §2.6). Lua threads are not related to operating-system threads. Lua supports coroutines on all systems, even those that do not support threads natively.

The type table implements associative arrays, that is, arrays that can have as indices not only numbers, but any Lua value except nil and NaN. (Not a Number is a special floating-point value used by the IEEE 754 standard to represent undefined numerical results, such as 0/0 .) Tables can be heterogeneous that is, they can contain values of all types (except nil). Any key associated to the value nil is not considered part of the table. Conversely, any key that is not part of a table has an associated value nil.

Tables are the sole data-structuring mechanism in Lua they can be used to represent ordinary arrays, lists, symbol tables, sets, records, graphs, trees, etc. To represent records, Lua uses the field name as an index. The language supports this representation by providing a.name as syntactic sugar for a["name"] . There are several convenient ways to create tables in Lua (see §3.4.9).

Like indices, the values of table fields can be of any type. In particular, because functions are first-class values, table fields can contain functions. Thus tables can also carry methods (see §3.4.11).

The indexing of tables follows the definition of raw equality in the language. The expressions a[i] and a[j] denote the same table element if and only if i and j are raw equal (that is, equal without metamethods). In particular, floats with integral values are equal to their respective integers (e.g., 1.0 == 1 ). To avoid ambiguities, any float used as a key that is equal to an integer is converted to that integer. For instance, if you write a[2.0] = true , the actual key inserted into the table will be the integer 2 .

Tables, functions, threads, and (full) userdata values are objects: variables do not actually contain these values, only references to them. Assignment, parameter passing, and function returns always manipulate references to such values these operations do not imply any kind of copy.

The library function type returns a string describing the type of a given value (see type ).


What’s new in Swift 5.4?

Multiple variadic parameters, improved implicit member syntax, result builders, and more!

Swift 5.4 brings with it some huge compilation improvements, including better code completion in expressions with errors and big speed ups for incremental compilation. However, it also adds some important new features and refinements, so let’s dig into them here…

SPONSORED A design tool made for SwiftUI. Kick-start your next design update with built-in SwiftUI design templates. Save time by skipping the need to set up a full development environment. Design for free with up to 5 files or get a full year of unlimited files and more for $29.99.

Improved implicit member syntax

SE-0287 improves Swift’s ability to use implicit member expressions, so rather than just having support for exactly one single static member you can make chains of them.

Swift has always had the ability to use implicit member syntax for simple expressions, for example if you wanted to color some text in SwiftUI you could use .red rather than Color.red :

Prior to Swift 5.4 this did not work with more complex expressions. For example, if you wanted your red color to be slightly transparent you would need to write this:

From Swift 5.4 onwards the compiler is able to understand multiple chained members, meaning that the Color type can be inferred:

Multiple variadic parameters in functions

SE-0284 introduced the ability to have functions, subscripts, and initializers use multiple variadic parameters as long as all parameters that follow a variadic parameter have labels. Before Swift 5.4, you could only have one variadic parameter in this situation.

So, with this improvement in place we could write a function that accepts a variadic parameter storing the times goals were scored during a football match, plus a second variadic parameter scoring the names of players who scored:

To call that function, provide both sets of values as variadic parameters, making sure that all parameters after the first variadic are labeled:

Creating variables that call a function of the same name

From Swift 5.4 onwards it’s possible to create a local variable by calling a function of the same name. That might sound obscure, but it’s actually a problem we hit all the time.

For example, this creates a struct with a color(forRow:) method, which gets called and assigned to a local variable called color :

That kind of usage is only allowed from Swift 5.4 and later. In earlier versions of Swift, it would create a circular reference because Swift couldn’t distinguish between the local color constant and the color(forRow:) method it was calling – you would have seen the error “Variable used within its own initial value”.

This usually resulted in us either using self.color(forRow: 1989) to make it clear we mean the method call, or just naming the local value something else such as colorForRow .

Fortunately Swift 5.4 resolves this and allows us to use the more natural naming.

This change also allows us to make local copies of properties and global variables. For example, we can take a copy of a username property that is also called username , like this:

Because this also applies to global variables, that same code works just fine even without the struct in place:

Result builders

Function builders unofficially arrived in Swift 5.1, but in the run up to Swift 5.4 they formally went through the Swift Evolution proposal process as SE-0289 in order to be discussed and refined. As part of that process they were renamed to result builders to better reflect their actual purpose, and even acquired some new functionality.

First up, the most important part: result builders allow us to create a new value step by step by passing in a sequence of our choosing. They power large parts of SwiftUI’s view creation system, so that when we have a VStack with a variety of views inside, Swift silently groups them together into an internal TupleView type so that they can be stored as a single child of the VStack – it turns a sequence of views into a single view.

Result builders deserve their own detailed article, but I at least want to give you some small code examples so you can see them in action.

Here is a function that returns a single string:

That works great, but what if had several strings we wanted to join together? Just like SwiftUI, we might want to provide them all individually and have Swift figure it out:

By itself, that code won’t work because Swift no longer understands what we mean. However, we could create a result builder that understands how to convert several strings into one string using whatever transformation we want, like this:

Even though that’s a small amount of code, there’s a lot to unpack:

  • The @resultBuilder attribute tells Swift the following type should be treated as a result builder. Previously this behavior was achieved using @_functionBuilder , which had an underscore to show that this wasn’t designed for general use.
  • Every result builder must provide at least one static method called buildBlock() , which should take in some sort of data and transform it. The example above takes in zero or more strings, joins them, and sends them back as a single string.
  • The end result is that our SimpleStringBuilder struct becomes a result builder, meaning that we can use @SimpleStringBuilder anywhere we need its string joining powers.

There’s nothing to stop us from using SimpleStringBuilder.buildBlock() directly, like this:

However, because we used the @resultBuilder annotation with our SimpleStringBuilder struct, we can also apply that to functions, like this:

Notice how we no longer need the commas at the end of each string – @resultBuilder automatically transforms each statement in makeSentence() into a single string by using SimpleStringBuilder .

In practice, result builders are capable of significantly more, accomplished by adding more methods to your builder type. For example, we could add if/else support to our SimpleStringBuilder by adding two extra methods that describe how we want to transform the data. In our code we don’t want to transform our strings at all, so we can send them right back:

I know that looks like we’ve done almost no work, but now our functions are able to use conditions:

Similarly, we could add support for loops by adding a buildArray() method to our builder type:

And now we can use for loops:

It feels almost like magic because the result builder system is doing almost all the work for us, and even though our example has been fairly simple I hope you can get a taste for the remarkable power result builders bring to Swift.

It’s worth adding that Swift 5.4 extends the result builder system to support attributes being placed on stored properties, which automatically adjusts the implicit memberwise initializer for structs to apply the result builder.

This is particularly helpful for custom SwiftUI views that use result builders, such as this one:

If you’d like to see more advanced, real-world examples of result builders in action, you should check out the Awesome Function Builders repository on GitHub.

Local functions now support overloading

SR-10069 requested the ability to overload functions in local contexts, which in practice means nested functions can now be overloaded so that Swift chooses which one to run based on the types that are used.

For example, if we wanted to make some simple cookies we might write code like this:

Prior to Swift 5.4, the three add() methods could be overloaded only if they were not nested inside makeCookies() , but from Swift 5.4 onwards function overloading is supported in this case as well.

Swift 5.4 also lets us call local functions before they are declared, meaning that we can now write code like this if needed:

Property wrappers are now supported for local variables

Property wrappers were first introduced in Swift 5.1 as a way of attaching extra functionality to properties in an easy, reusable way, but in Swift 5.4 their behavior got extended to support using them as local variables in functions.

For example, we could create a property wrapper that ensures its value never goes below zero:

And from Swift 5.4 onwards we can use that property wrapper inside a regular function, rather than just attaching to a property. For example, we might write a game where our player can gain or lose points, but their score should never go below 0:

Packages can now declare executable targets

SE-0294 adds a new target option for apps using Swift Package manager, allowing us to explicitly declare an executable target.

This is particularly important for folks who want to use SE-0281 (using @main to mark your program’s entry point), because it didn’t play nicely with Swift Package Manager – it would always look for a main.swift file.

With this change, we can now remove main.swift and use @main instead. Note: You must specify // swift-tools-version:5.4 in your Package.swift file in order to get this new functionality.

Trying it yourself

Swift 5.4 is available through Xcode 12.5, which is available from the Mac App Store.

Which features of Swift 5.4 are you most looking forward to?

SPONSORED A design tool made for SwiftUI. Kick-start your next design update with built-in SwiftUI design templates. Save time by skipping the need to set up a full development environment. Design for free with up to 5 files or get a full year of unlimited files and more for $29.99.

About the author

Paul Hudson is the creator of Hacking with Swift, the most comprehensive series of Swift books in the world. He's also the editor of Swift Developer News, the maintainer of the Swift Knowledge Base, and a speaker at Swift events around the world. If you're curious you can learn more here.


5.4: Logarithmic Functions

The composition of a function with its inverse returns the starting value, x.

This concept will be used to solve equations involving exponentials and logarithms.

Now that we have a basic idea of a logarithmic function, let's take a closer look at its graph.

Let's examine the function:

The value of b (the 2) is referred to as the base of the logarithm.

Notice that x must be positive.

Note: In a linear graph, the " rate of change " remains the same across the entire graph.
In a logarithmic graph, the "rate of change" increases (or decreases) across the graph.

For help with logarithms on
your calculator,
click here.

For "other bases" use the following "change of base" conversion:


Or use logBASE( template at MATH &rarr arrow down to A:logBASE(.

The graphs of functions of the form have certain characteristics in common.

• graph crosses the x-axis at (1,0)

• when b > 1, the graph increases

• when 0 < b < 1, the graph decreases

• the domain is all positive real numbers (never zero)

• the range is all real numbers

• graph passes the vertical line test for functions

• graph passes the horizontal line test for functional inverse.

• graph is asymptotic to the y-axis - gets very, very close to the y-axis but, in this case, does not touch it or cross it.

We know that transformations have the ability to move functions by sliding them, reflecting them, stretching them, and shrinking them. Let's see how these changes will affect the logarithmic function:

Parent function:

Translation y = logb(x - h) + k
horizontal by h: vertical by k:


Domain: x > h
Range: x &isin Real numbers

All 3 transformations combined: y = a logb(x - h) + k

By examining the nature of the logarithmic graph, we have seen that the parent function will stay to the right of the x-axis, unless acted upon by a transformation.
• The parent function , y = logb x, will always have an x-intercept of one , occurring at the ordered pair of (1,0).
There is no y-intercept with the parent function since it is asymptotic to the y-axis (approaches the y-axis but does not touch or cross it).

• The transformed parent function of the form y = alogb x, will also always have a x-intercept of 1 , occurring at the ordered pair of (1, 0). Note that the value of a may be positive or negative.
Like the parent function, this transformation will be asymptotic to the y-axis, and will have no y-intercept.


• If the transformed parent function includes a vertical or horizontal shift , all bets are off. The horizontal shift will affect the possibility of a y-intercept and the vertical shift will affect the x-intercept. In this situation, you will need to examine the graph carefully to determine what is happening.

• The end behavior of a transformed parent function is not always consistent, but is dependent upon the nature of the transformation. Consider this example:

For the transformed equation

the horizontal shift of +5 will push the
asymptote line to the left five units.
Thus the end behavior will be:

The y-intercept, where x = 0, is
y =log 2 (0 + 5) + 4 &asymp 6.321928095.
The x-intercept, where y = 0, is
approximately -4.94 (from the graph's table) .



Don't confuse log graphs
with square root graphs.
At fist glance, these two graphs appear to be similar. But the square root graph is actually ending, while the log graph is not.


End Behavior of a Function

The end behavior of a polynomial function is the behavior of the graph of f ( x ) as x approaches positive infinity or negative infinity.

The degree and the leading coefficient of a polynomial function determine the end behavior of the graph.

The leading coefficient is significant compared to the other coefficients in the function for the very large or very small numbers. So, the sign of the leading coefficient is sufficient to predict the end behavior of the function.

Leading Coefficient

To predict the end-behavior of a polynomial function, first check whether the function is odd-degree or even-degree function and whether the leading coefficient is positive or negative.

Find the end behavior of the function x 4 − 4 x 3 + 3 x + 25 .

The degree of the function is even and the leading coefficient is positive. So, the end behavior is:

f ( x ) → + ∞ , as x → − ∞ f ( x ) → + ∞ , as x → + ∞

The graph looks as follows:

Download our free learning tools apps and test prep books

Names of standardized tests are owned by the trademark holders and are not affiliated with Varsity Tutors LLC.

4.9/5.0 Satisfaction Rating over the last 100,000 sessions. As of 4/27/18.

Media outlet trademarks are owned by the respective media outlets and are not affiliated with Varsity Tutors.

Award-Winning claim based on CBS Local and Houston Press awards.

Varsity Tutors does not have affiliation with universities mentioned on its website.

Varsity Tutors connects learners with experts. Instructors are independent contractors who tailor their services to each client, using their own style, methods and materials.


Logarithmic Differentiation

The method of differentiating functions by first taking logarithms and then differentiating is called logarithmic differentiation . We use logarithmic differentiation in situations where it is easier to differentiate the logarithm of a function than to differentiate the function itself. This approach allows calculating derivatives of power, rational and some irrational functions in an efficient manner.

Consider this method in more detail. Let (y = fleft( x ight)). Take natural logarithms of both sides:

Next, we differentiate this expression using the chain rule and keeping in mind that (y) is a function of (x.)

It’s seen that the derivative is

The derivative of the logarithmic function is called the logarithmic derivative of the initial function (y = fleft( x ight).)

This differentiation method allows to effectively compute derivatives of power-exponential functions, that is functions of the form

where (uleft( x ight)) and (vleft( x ight)) are differentiable functions of (x.)

In the examples below, find the derivative of the function (yleft( x ight)) using logarithmic differentiation.


5.4: Logarithmic Functions

We know that the sign of the derivative tells us whether a function is increasing or decreasing for example, when $f'(x)>0$, $f(x)$ is increasing. The sign of the second derivative $f''(x)$ tells us whether $f'$ is increasing or decreasing we have seen that if $f'$ is zero and increasing at a point then there is a local minimum at the point, and if $f'$ is zero and decreasing at a point then there is a local maximum at the point. Thus, we extracted information about $f$ from information about $f''$.

We can get information from the sign of $f''$ even when $f'$ is not zero. Suppose that $f''(a)>0$. This means that near $x=a$, $f'$ is increasing. If $f'(a)>0$, this means that $f$ slopes up and is getting steeper if $f'(a) Figure 5.4.1. $f''(a)>0$: $f'(a)$ positive and increasing, $f'(a)$ negative and increasing.

Now suppose that $f''(a) 0$, this means that $f$ slopes up and is getting less steep if $f'(a) Figure 5.4.2. $f''(a) Example 5.4.1 Describe the concavity of $ds f(x)=x^3-x$. $ds f'(x)=3x^2-1$, $f''(x)=6x$. Since $f''(0)=0$, there is potentially an inflection point at zero. Since $f''(x)>0$ when $x>0$ and $f''(x) 0$.

Note that we need to compute and analyze the second derivative to understand concavity, so we may as well try to use the second derivative test for maxima and minima. If for some reason this fails we can then try one of the other tests.


Lesson 4

In this lesson, students work with graphs and tables that represent functions in addition to the equations and descriptions used previously. They learn the conventions of graphing the independent variable (input) on the horizontal axis and the dependent variable (output) on the vertical axis and that each coordinate point represents an input-output pair of the function.

By matching contexts and graphs and reading information about functions from graphs and tables, students become familiar with the different representations and draw connections between them.

Learning Goals

Let’s connect equations and graphs of functions.

Learning Targets

CCSS Standards

Glossary Entries

A dependent variable represents the output of a function.

For example, suppose we need to buy 20 pieces of fruit and decide to buy apples and bananas. If we select the number of apples first, the equation (b=20-a) shows the number of bananas we can buy. The number of bananas is the dependent variable because it depends on the number of apples.

An independent variable represents the input of a function.

For example, suppose we need to buy 20 pieces of fruit and decide to buy some apples and bananas. If we select the number of apples first, the equation (b=20-a) shows the number of bananas we can buy. The number of apples is the independent variable because we can choose any number for it.

A radius is a line segment that goes from the center to the edge of a circle. A radius can go in any direction. Every radius of the circle is the same length. We also use the word radius to mean the length of this segment.

For example, (r) is the radius of this circle with center (O) .

Expand Image

Print Formatted Materials

Teachers with a valid work email address can click here to register or sign in for free access to Cool Down, Teacher Guide, and PowerPoint materials.

Additional Resources

IM 6–8 Math was originally developed by Open Up Resources and authored by Illustrative Mathematics®, and is copyright 2017-2019 by Open Up Resources. It is licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0). OUR's 6–8 Math Curriculum is available at https://openupresources.org/math-curriculum/.

Adaptations and updates to IM 6–8 Math are copyright 2019 by Illustrative Mathematics, and are licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0).

Adaptations to add additional English language learner supports are copyright 2019 by Open Up Resources, and are licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0).

The second set of English assessments (marked as set "B") are copyright 2019 by Open Up Resources, and are licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0).

Spanish translation of the "B" assessments are copyright 2020 by Illustrative Mathematics, and are licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0).

The Illustrative Mathematics name and logo are not subject to the Creative Commons license and may not be used without the prior and express written consent of Illustrative Mathematics.

This site includes public domain images or openly licensed images that are copyrighted by their respective owners. Openly licensed images remain under the terms of their respective licenses. See the image attribution section for more information.


5.4: Logarithmic Functions

The ECMAScript 2017 feature 𠇊sync Functions” was proposed by Brian Terlson.

5.1 Overview #

5.1.1 Variants #

The following variants of async functions exist. Note the keyword async everywhere.

  • Async function declarations: async function foo() <>
  • Async function expressions: const foo = async function () <>
  • Async method definitions: let obj = < async foo() <>>
  • Async arrow functions: const foo = async () => <>

5.1.2 Async functions always return Promises #

Fulfilling the Promise of an async function:

Rejecting the Promise of an async function:

5.1.3 Handling results and errors of asynchronous computations via await #

The operator await (which is only allowed inside async functions) waits for its operand, a Promise, to be settled:

  • If the Promise is fulfilled, the result of await is the fulfillment value.
  • If the Promise is rejected, await throws the rejection value.

Handling a single asynchronous result:

Handling multiple asynchronous results sequentially:

Handling multiple asynchronous results in parallel:

5.2 Understanding async functions #

Before I can explain async functions, I need to explain how Promises and generators can be combined to perform asynchronous operations via synchronous-looking code.

For functions that compute their one-off results asynchronously, Promises, which are part of ES6, have become popular. One example is the client-side fetch API, which is an alternative to XMLHttpRequest for retrieving files. Using it looks as follows:

5.2.1 Writing asynchronous code via generators #

co is a library that uses Promises and generators to enable a coding style that looks more synchronous, but works the same as the style used in the previous example:

Every time the callback (a generator function!) yields a Promise to co, the callback gets suspended. Once the Promise is settled, co resumes the callback: if the Promise was fulfilled, yield returns the fulfillment value, if it was rejected, yield throws the rejection error. Additionally, co promisifies the result returned by the callback (similarly to how then() does it).

5.2.2 Writing asynchronous code via async functions #

Async functions are basically dedicated syntax for what co does:

Internally, async functions work much like generators.

5.2.3 Async functions are started synchronously, settled asynchronously #

This is how async functions are executed:

  1. The result of an async function is always a Promise p . That Promise is created when starting the execution of the async function.
  2. The body is executed. Execution may finish permanently via return or throw . Or it may finish temporarily via await in which case execution will usually continue later on.
  3. The Promise p is returned.

While executing the body of the async function, return x resolves the Promise p with x , while throw err rejects p with err . The notification of a settlement happens asynchronously. In other words: the callbacks of then() and catch() are always executed after the current code is finished.

The following code demonstrates how that works:

You can rely on the following order:

  1. Line (A): the async function is started synchronously. The async function’s Promise is resolved via return .
  2. Line (C): execution continues.
  3. Line (B): Notification of Promise resolution happens asynchronously.

5.2.4 Returned Promises are not wrapped #

Resolving a Promise is a standard operation. return uses it to resolve the Promise p of an async function. That means:

  1. Returning a non-Promise value fulfills p with that value.
  2. Returning a Promise means that p now mirrors the state of that Promise.

Therefore, you can return a Promise and that Promise won’t be wrapped in a Promise:

Intriguingly, returning a rejected Promise leads to the result of the async function being rejected (normally, you𠆝 use throw for that):

That is in line with how Promise resolution works. It enables you to forward both fulfillments and rejections of another asynchronous computation, without an await :

The previous code is roughly similar to – but more efficient than – the following code (which unwraps the Promise of anotherAsyncFunc() only to wrap it again):

5.3 Tips for using await #

5.3.1 Don’t forget await #

One easy mistake to make in async functions is to forget await when making an asynchronous function call:

In this example, value is set to a Promise, which is usually not what you want in async functions.

await can even make sense if an async function doesn’t return anything. Then its Promise is simply used as a signal for telling the caller that it is finished. For example:

The await in line (A) guarantees that step1() is completely finished before the remainder of foo() is executed.

5.3.2 You don’t need await if you 𠇏ire and forget” #

Sometimes, you only want to trigger an asynchronous computation and are not interested in when it is finished. The following code is an example:

Here, we don’t care when individual writes are finished, only that they are executed in the right order (which the API would have to guarantee, but that is encouraged by the execution model of async functions – as we have seen).

The await in the last line of asyncFunc() ensures that the function is only fulfilled after the file was successfully closed.

Given that returned Promises are not wrapped, you can also return instead of await writer.close() :

Both versions have pros and cons, the await version is probably slightly easier to understand.

5.3.3 await is sequential, Promise.all() is parallel #

The following code make two asynchronous function calls, asyncFunc1() and asyncFunc2() .

However, these two function calls are executed sequentially. Executing them in parallel tends to speed things up. You can use Promise.all() to do so:

Instead of awaiting two Promises, we are now awaiting a Promise for an Array with two elements.

5.4 Async functions and callbacks #

One limitation of async functions is that await only affects the directly surrounding async function. Therefore, an async function can’t await in a callback (however, callbacks can be async functions themselves, as we’ll see later on). That makes callback-based utility functions and methods tricky to use. Examples include the Array methods map() and forEach() .

5.4.1 Array.prototype.map() #

Let’s start with the Array method map() . In the following code, we want to download the files pointed to by an Array of URLs and return them in an Array.

This does not work, because await is syntactically illegal inside normal arrow functions. How about using an async arrow function, then?

There are two issues with this code:

  • The result is now an Array of Promises, not an Array of strings.
  • The work performed by the callbacks isn’t finished once map() is finished, because await only pauses the surrounding arrow function and httpGet() is resolved asynchronously. That means you can’t use await to wait until downloadContent() is finished.

We can fix both issues via Promise.all() , which converts an Array of Promises to a Promise for an Array (with the values fulfilled by the Promises):

The callback for map() doesn’t do much with the result of httpGet() , it only forwards it. Therefore, we don’t need an async arrow function here, a normal arrow function will do:

There is one small improvement that we still can make: This async function is slightly inefficient – it first unwraps the result of Promise.all() via await , before wrapping it again via return . Given that return doesn’t wrap Promises, we can return the result of Promise.all() directly:

5.4.2 Array.prototype.forEach() #

Let’s use the Array method forEach() to log the contents of several files pointed to via URLs:

Again, this code will produce a syntax error, because you can’t use await inside normal arrow functions.

Let’s use an async arrow function:

This does work, but there is one caveat: the Promise returned by httpGet() is resolved asynchronously, which means that the callbacks are not finished when forEach() returns. As a consequence, you can’t await the end of logContent() .

If that’s not what you want, you can convert forEach() into a for-of loop:

Now everything is finished after the for-of loop. However, the processing steps happen sequentially: httpGet() is only called a second time after the first call is finished. If you want the processing steps to happen in parallel, you must use Promise.all() :

map() is used to create an Array of Promises. We are not interested in the results they fulfill, we only await until all of them are fulfilled. That means that we are completely done at the end of this async function. We could just as well return Promise.all() , but then the result of the function would be an Array whose elements are all undefined .

5.5 Tips for using async functions #

5.5.1 Know your Promises #

The foundation of async functions is Promises. That’s why understanding the latter is crucial for understanding the former. Especially when connecting old code that isn’t based on Promises with async functions, you often have no choice but to use Promises directly.

For example, this is a “promisified” version of XMLHttpRequest :

The API of XMLHttpRequest is based on callbacks. Promisifying it via an async function would mean that you𠆝 have to fulfill or reject the Promise returned by the function from within callbacks. That’s impossible, because you can only do so via return and throw . And you can’t return the result of a function from within a callback. throw has similar constraints.

Therefore, the common coding style for async functions will be:

  • Use Promises directly to build asynchronous primitives.
  • Use those primitives via async functions.

5.5.2 Immediately Invoked Async Function Expressions #

Sometimes, it𠆝 be nice if you could use await at the top level of a module or script. Alas, it’s only available inside async functions. You therefore have several options. You can either create an async function main() and call it immediately afterwards:

Or you can use an Immediately Invoked Async Function Expression:

Another option is an Immediately Invoked Async Arrow Function:

5.5.3 Unit testing with async functions #

The following code uses the test-framework mocha to unit-test the asynchronous functions asyncFunc1() and asyncFunc2() :

However, this test always succeeds, because mocha doesn’t wait until the assertions in line (B) and line (C) are executed.

You can fix this by returning the result of the Promise chain, because mocha recognizes if a test returns a Promise and then waits until that Promise is settled (unless there is a timeout).

Conveniently, async functions always return Promises, which makes them perfect for this kind of unit test:

There are thus two advantages to using async functions for asynchronous unit tests in mocha: the code is more concise and returning Promises is taken care of, too.

5.5.4 Don’t worry about unhandled rejections #

JavaScript engines are becoming increasingly good at warning about rejections that are not handled. For example, the following code would often fail silently in the past, but most modern JavaScript engines now report an unhandled rejection:


Watch the video: Sec Logarithmic Functions and Models (January 2022).