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 |
---|---|---|---|---|
|
✓ |
8 |
-2^7 |
2^7 - 1 |
|
8 |
0 |
2^8 - 1 |
|
|
✓ |
16 |
-2^15 |
2^15 - 1 |
|
16 |
0 |
2^16 - 1 |
|
|
✓ |
32 |
-2^31 |
2^31 - 1 |
|
32 |
0 |
2^32 - 1 |
|
|
✓ |
64 |
-2^63 |
2^63 - 1 |
|
64 |
0 |
2^64 - 1 |
|
|
✓ |
128 |
-2^127 |
2^127 - 1 |
|
128 |
0 |
2^128 - 1 |
|
|
N/A |
8 |
|
|
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 |
---|---|---|
|
half |
16 |
|
single |
32 |
|
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 |
---|---|---|
|
unary plus |
The identity operation |
|
unary minus |
Maps a value to its additive inverse |
|
binary plus |
Performs addition |
|
binary minus |
Performs subtraction |
|
times |
Performs multiplication |
|
divide |
Performs division |
|
integer divide |
|
|
inverse divide |
Equivalent to |
|
power |
Raises |
|
remainder |
Equivalent to |
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)
.