1.1. Julia as a Calculator#

1.1.1. Arithmetic#

At its most basic level, you can use Julia as a powerful calculator. Let’s start by evaluating some simple arithmetic expressions.

123.4 + 234.5     # The '#' character starts a comment, which is ignored by Julia.
357.9
7 / 3             # Standard division with `/` always returns a floating-point number.
2.3333333333333335
7 ÷ 3             # For truncated integer division, use the `÷` operator (type \div then press Tab).
2
7 % 3             # The `%` operator calculates the remainder of a division.
1
2^7 - 4           # An expression involving only integers returns an integer.
124
3 * (4.2 - 9.7)   # Use parentheses to control the order of operations.
-16.499999999999996
# We'll explore why the previous result isn't exact in a later chapter on floating-point numbers.
5.6e7 ^ 0.1       # Julia supports scientific notation: `5.6e7` means 5.6 × 10⁷.
5.954136718963118

1.1.2. Multiple Lines in a Cell#

A Jupyter cell with multiple lines of code will only display the output of the final line.

1 + 2
34 / 3
11.333333333333334

You can suppress the output of any line by ending it with a semicolon (;). To display multiple outputs or add descriptive text, use the println() function.

println(1 + 2.1)
println("The result is ", -123 / 1000000)
34 / 3; # This output is suppressed by the semicolon.
3.1
The result is -0.000123

1.1.3. Primitive Numeric Data Types#

As we’ve seen, Julia automatically chooses an appropriate data type (like an integer or a floating-point number) for your values. However, it’s often useful to understand which types are being used and how to specify them manually.

The typeof() function reveals the data type of any value:

typeof(1.23)
Float64
typeof(-745)
Int64
typeof(1e20)
Float64

1.1.3.1. Integer Types#

Julia provides a range of primitive integer types, which differ in the number of bits they use for storage and whether they can store negative values (signed vs. unsigned).

Type

Signed?

Number of bits

Smallest value

Largest value

Int8

8

-2^7

2^7 - 1

UInt8

8

0

2^8 - 1

Int16

16

-2^15

2^15 - 1

UInt16

16

0

2^16 - 1

Int32

32

-2^31

2^31 - 1

UInt32

32

0

2^32 - 1

Int64

64

-2^63

2^63 - 1

UInt64

64

0

2^64 - 1

Int128

128

-2^127

2^127 - 1

UInt128

128

0

2^128 - 1

Bool

N/A

8

false (0)

true (1)

The typemin() and typemax() functions show the range of values a numeric type can represent:

println(typemin(Int64))  # Smallest 64-bit signed integer
println(typemax(Int64))  # Largest 64-bit signed integer
println(typemin(Int128)) # Smallest 128-bit signed integer
println(typemax(Int128)) # Largest 128-bit signed integer
-9223372036854775808
9223372036854775807
-170141183460469231731687303715884105728
170141183460469231731687303715884105727

On a 64-bit system, Julia’s default integer type is Int64. If a calculation exceeds the maximum value this type can hold, it results in an overflow error, where the number ‘wraps around’, leading to an incorrect answer. For example, consider the computation of \(1000^7\):

1000^7 # This calculation overflows, producing an incorrect result.
3875820019684212736

This result is clearly wrong. To handle such large numbers, we can explicitly use a larger integer type like Int128.

Int128(1000)^7 # By converting 1000 to Int128 first, the calculation is correct.
1000000000000000000000

Choosing the right data type is crucial. For calculations requiring a very high number of digits (limited only by memory and time), Julia provides an arbitrary-precision integer type called BigInt. You can create one using the big"..." string macro:

big"1000"^7
1000000000000000000000
big"1234567890"^100 # This calculation is exact, thanks to BigInt.
1417417260103558770214252423976142668502309843289216833019048237594757708238986182489372231899746980921982728329402793285767462862882464121635860400730716254039942351084846547018518131114125220170734365519774681825663555080960088448187700306662591033835497547065849829393393851336850513516716654954594842407071059129565467264692831108320130483612672587797723547589358874240495338978427064891700798459028240889817739929243620390292500203679620864971533914260827834601579209314189120626901904458486936727622905582367388818325467159626747054599568953786703562122799941680845141148189896305104641344839457223830507901762718528867396981775965176554700698356765830690713630912519126290583362303892345035739308972274807594103376959348593678587147932967060392101430789829817061010598621196674073173467189374435975660010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Note that when an expression involves a BigInt and a standard integer (like the exponents above), Julia automatically promotes the entire calculation to use BigInt to maintain precision.

We’ll dive deeper into these special number types in a later chapter.

1.1.3.2. Floating-Point Types#

Julia also has primitive floating-point types for representing real numbers:

Type

Precision

Number of bits

Float16

half

16

Float32

single

32

Float64

double

64

We will discuss precision in detail later, but for now, here are the key takeaways:

  • The default type for decimal numbers is Float64, also known as double precision.

  • It can represent a number with about 16 decimal digits of accuracy.

  • Its range is approximately from \(10^{-308}\) to \(10^{308}\).

10 / 3
3.3333333333333335
(10 / 3) ^ 589   # This is OK (just barely within the Float64 range).
9.453246228910832e307
(10 / 3) ^ 590   # This calculation exceeds the Float64 range, resulting in `Inf` (infinity).
Inf

Similar to BigInt, Julia provides BigFloat for arbitrary-precision floating-point arithmetic. This is useful when you need more precision than the standard Float64 can offer. You can create a BigFloat using the big"..." string macro:

big"10" / 3 # Note the increased number of digits compared to the standard 10 / 3.
3.333333333333333333333333333333333333333333333333333333333333333333333333333322
(big"10" / 3) ^ 1000000    # This works perfectly, avoiding the overflow error seen with Float64.
5.562632099157128865882114862625068529147801916401519743970961486254075585953082e+522878

As with integers, Julia automatically promotes the other numbers in the expression (like 3 and 1000000) to the most general type, ensuring that the entire calculation is performed using BigFloat’s high precision.

1.1.4. Arithmetic Operators and Order of Operations#

Expression

Name

Description

+x

unary plus

The identity operation

-x

unary minus

Maps a value to its additive inverse

x + y

binary plus

Performs addition

x - y

binary minus

Performs subtraction

x * y

times

Performs multiplication

x / y

divide

Performs division

x ÷ y

integer divide

x / y, truncated to an integer

x \ y

inverse divide

Equivalent to y / x

x ^ y

power

Raises x to the y-th power

x % y

remainder

Equivalent to rem(x,y)

Julia follows the standard mathematical order of operations:

  • Parentheses ()

  • Exponentiation ^

  • Multiplication * and Division /

  • Addition + and Subtraction -

Operators with the same precedence are evaluated from left to right (except for ^, which is right-associative).

For example, 360 / 2 * pi evaluates to (360 / 2) * pi, which is 180 * pi. Always use parentheses to clarify the order when in doubt, e.g., 360 / (2 * pi).