Julia Data Types

In programming languages, there are basic mathematical operations and scientific calculations. Their commonly used data types areintegersandfloating-pointnumbers.

In addition, there is also a"literal"term. A literal is a notation used to express a fixed value in source code. Integers, floating-point numbers, strings, etc. are all literals.

For example:

a=1 // a is a variable, 1 is an integer literal b=1.0 // b is a variable, 1.0 is a floating-point literal

Julia provides a rich set of primitive numeric types, and defines a complete set of arithmetic operations based on them. In addition, it also provides bitwise operators and some standard mathematical functions.


Integer Types

The following table lists the integer types supported by Julia:

Type Signed? Number of bits Minimum value Maximum 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)

Integer literal forms:

Example

julia> 1
1

julia> 1234
1234

The default type of an integer literal depends on whether the target system is a 32-bit or 64-bit architecture (most systems today are 64-bit):

Example

# 32-bit system:
julia> typeof(1)
Int32

# 64-bit system:
julia> typeof(1)
Int64

Julia's built-in variableSys.WORD_SIZEindicates whether the target system is a 32-bit or 64-bit architecture:

Example

# 32-bit system:
julia> Sys.WORD_SIZE
32

# 64-bit system:
julia> Sys.WORD_SIZE
64

Julia also defines Int and UInt types, which are aliases for the system's signed and unsigned native integer types, respectively.

Example

# 32-bit system:
julia> Int
Int32
julia> UInt
UInt32

# 64-bit system:
julia> Int
Int64
julia> UInt
UInt64

Overflow Behavior

In Julia, exceeding the maximum value representable by a type causes wraparound behavior:

Example

julia> x = typemax(Int64)
9223372036854775807

julia> x + 1
-9223372036854775808

julia> x + 1 == typemin(Int64)
true

Therefore, Julia's integer arithmetic is actually a form of modular arithmetic, reflecting the characteristics of how modern computers implement low-level arithmetic. In programs where overflow may occur, explicit checks for wraparound at the boundaries of the extreme values are necessary. Otherwise, the BigInt type from arbitrary-precision arithmetic is recommended as an alternative.

Below is an example of overflow behavior and how to solve overflow:

Example

julia> 10^19
-8446744073709551616

julia> big(10)^19
10000000000000000000

Division Errors

Integer division triggers a DivideError in the following two exceptional cases:
  • Division by zero
  • Division by the smallest negative number

remThe remainder function andmodthe modulus function throw a DivideError when dividing by zero. Here is an example:

Example

julia> mod(1, 0)
ERROR: DivideError: integer division error
Stacktrace:
 [1] div at .\int.jl:260 [inlined]
 [2] div at .\div.jl:217 [inlined]
 [3] div at .\div.jl:262 [inlined]
 [4] fld at .\div.jl:228 [inlined]
 [5] mod(::Int64, ::Int64) at .\int.jl:252
 [6] top-level scope at REPL[52]:1
 
 
julia> rem(1, 0)
ERROR: DivideError: integer division error
Stacktrace:
 [1] rem(::Int64, ::Int64) at .\int.jl:261
 [2] top-level scope at REPL[54]:1

Floating-Point Types

The following table lists the floating-point types supported by Julia:

Type Precision Number of bits
Float16 Half precision 16
Float32 Single precision 32
Float64 Double precision 64

In addition, full support for complex and rational numbers is built on top of these primitive data types.

The format of floating-point literals is shown below. When necessary, you can useEto express it.

Example

julia> 1.0
1.0

julia> 1.
1.0

julia> 0.5
0.5

julia> .5
0.5

julia> -1.23
-1.23

julia> 1e10
1.0e10

julia> 2.5e-4
0.00025

Note:

In scientific notation, to simplify formulas, the format withEcan be used for representation. For example, 1.03 times 10 to the 8th power can be abbreviated as "1.03E+08", where "E" is the abbreviation of exponent.

The results above are all Float64 values. Using f instead of e yields Float32 literals:

Example

julia> x = 0.5f0
0.5f0

julia> typeof(x)
Float32

julia> 2.5f-4
0.00025f0
Numbers can be easily converted toFloat32type:

julia> x = Float32(-1.5)
-1.5f0

julia> typeof(x)
Float32

There are also hexadecimal floating-point literals, but they only apply to values of the Float64 type. They are generally represented using the p prefix and an exponent with base 2:

Example

julia> 0x1p0
1.0

julia> 0x1.8p3
12.0

julia> x = 0x.4p-1
0.125

julia> typeof(x)
Float64
Julia also supports half-precision floating-point numbers (Float16), but they areFloat32implemented through software emulation.

julia> sizeof(Float16(4.))
2

julia> 2*Float16(4.)
Float16(8.0)

Underscore_can be used as a digit separator:

Example

julia> 10_000, 0.000_000_005, 0xdead_beef, 0b1011_0010
(10000, 5.0e-9, 0xdeadbeef, 0xb2)

Zero in Floating-Point Numbers

Floating-point numbers have two kinds of zeros: positive zero and negative zero. They are equal to each other but have different binary representations, which can be viewed using the bitstring function:

Example

julia> 0.0 == -0.0
true

julia> bitstring(0.0)
"0000000000000000000000000000000000000000000000000000000000000000"

julia> bitstring(-0.0)
"1000000000000000000000000000000000000000000000000000000000000000"

Special Floating-Point Values

There are three specific standard floating-point values that do not correspond to any point on the real number line:

Float16 Float32 Float64 Name Description
Inf16 Inf32 Inf Positive infinity A number greater than all finite floating-point numbers
-Inf16 -Inf32 -Inf Negative infinity A number less than all finite floating-point numbers
NaN16 NaN32 NaN Not a number A value that is not equal (==) to any floating-point value (including itself)

The following lists some examples of operations on floating-point numbers:

Example

julia> 1/Inf
0.0

julia> 1/0
Inf

julia> -5/0
-Inf

julia> 0.000001/0
Inf

julia> 0/0
NaN

julia> 500 + Inf
Inf

julia> 500 - Inf
-Inf

julia> Inf + Inf
Inf

julia> Inf - Inf
NaN

julia> Inf * Inf
Inf

julia> Inf / Inf
NaN

julia> 0 * Inf
NaN

julia> NaN == NaN
false

julia> NaN != NaN
true

julia> NaN < NaN
false

julia> NaN > NaN
false

We can also use the typemin and typemax functions:

Example

julia> (typemin(Float16),typemax(Float16))
(-Inf16, Inf16)

julia> (typemin(Float32),typemax(Float32))
(-Inf32, Inf32)

julia> (typemin(Float64),typemax(Float64))
(-Inf, Inf)

Machine Precision

Most real numbers cannot be represented exactly by floating-point numbers, so it is necessary to know the distance between two adjacent representable floating-point numbers, which is usually called machine precision.

Julia provides theepsfunction, which gives the difference between 1.0 and the next floating-point number that Julia can represent:

Example

julia> eps(Float32)
1.1920929f-7

julia> eps(Float64)
2.220446049250313e-16

julia> eps() # Same as eps(Float64)
2.220446049250313e-16

These values are 2.0^-23 in Float32 and 2.0^-52 in Float64, respectively. The eps function can also take a floating-point value as an argument and return the absolute difference between this value and the next representable floating-point value. That is, eps(x) yields a value of the same type as x, and x + eps(x) is exactly the next representable floating-point value greater than x:

Example

julia> eps(1.0)
2.220446049250313e-16

julia> eps(1000.)
1.1368683772161603e-13

julia> eps(1e-27)
1.793662034335766e-43

julia> eps(0.0)
5.0e-324

The distance between two adjacent representable floating-point numbers is not constant: the smaller the number, the smaller the gap; the larger the number, the larger the gap. In other words, representable floating-point numbers are densest near zero on the real number line, and become increasingly sparse exponentially as they move away from zero. By definition, eps(1.0) is equal to eps(Float64), because 1.0 is a 64-bit floating-point value.

Julia also provides two functions, nextfloat and prevfloat, which return the next greater or smaller representable floating-point number based on the argument, respectively:

Example

julia> x = 1.25f0
1.25f0

julia> nextfloat(x)
1.2500001f0

julia> prevfloat(x)
1.2499999f0

julia> bitstring(prevfloat(x))
"00111111100111111111111111111111"

julia> bitstring(x)
"00111111101000000000000000000000"

julia> bitstring(nextfloat(x))
"00111111101000000000000000000001"

This example illustrates the general principle that adjacent representable floating-point numbers also have adjacent binary integer representations.


Rounding Modes

If a number does not have an exact floating-point representation, it must be rounded to a suitable representable value.

The default mode used by Julia is alwaysRoundNearest, which means rounding to the nearest representable value, and the rounded value uses as few significant digits as possible.

Example

julia> BigFloat("1.510564889",2,RoundNearest)
1.5

julia> BigFloat("1.550564889",2,RoundNearest)
1.5

julia> BigFloat("1.560564889",2,RoundNearest)
1.5

Zero and One Literals

Julia provides literal functions for 0 and 1, which can return the literal of a specific type or the type of a given variable.

FunctionDescription
zero(x)Zero literal of type x or of the type of variable x
one(x)One literal of type x or of the type of variable x

These functions can be used in numerical comparisons to avoid the overhead of unnecessary type conversions.

For example:

Example

julia> zero(Float32)
0.0f0

julia> zero(1.0)
0.0

julia> one(Int32)
1

julia> one(BigFloat)
1.0

Type Conversion

Type conversion is the process of converting a variable from one type to another data type. For example, if you want to store a float value in a simple integer, you need to cast the float type to an int type. You can use the cast operator to explicitly convert a value from one type to another, as shown below:

Julia supports three kinds of numeric conversion, which differ in how they handle inexact conversions.

The first kind:

T(x) 
或
convert(T,x) 

All of the above convert x to type T.

  • If T is a floating-point type, the result is the nearest representable value, which may be positive or negative infinity.
  • If T is an integer type, an InexactError is thrown when x cannot be represented by type T.

The second kind:

x % TIt is also possible to convert an integer x to an integer type T, consistent with the result of x modulo 2^n, where n is the number of bits in T.

The third kind:

The rounding functions take an optional argument of type T. For example, round(Int,x) isInt(round(x))the abbreviated form.

Example

julia> Int8(127)
127

julia> Int8(128)
ERROR: InexactError: trunc(Int8, 128)
Stacktrace:
[...]

julia> Int8(127.0)
127

julia> Int8(3.14)
ERROR: InexactError: Int8(3.14)
Stacktrace:
[...]

julia> Int8(128.0)
ERROR: InexactError: Int8(128.0)
Stacktrace:
[...]

julia> 127 % Int8
127

julia> 128 % Int8
-128

julia> round(Int8,127.4)
127

julia> round(Int8,127.6)
ERROR: InexactError: trunc(Int8, 128.0)
Stacktrace:
[...]
Other Extensions