May 14, 2021 Julia
Integers and floats are the basis of arithmetic and calculation. T
hey are all numeric text.
For
1
is integer text,
1.0
is floating-point text.
Julia provides a wealth of underlying numeric types, all arithmetic and bit operators, and standard mathematical functions. T hese data and operations correspond directly to operations supported by modern computers. A s a result, Julia can take full advantage of the computing resources of the hardware. In addition, Julia supports any precision arithmetic at the software level and can be used to represent values that hardware cannot natively support, although this sacrifices some computing efficiency.
The underlying numeric types provided by Julia are:
Char
natively supports Unicode
characters;
Floating point type:
Type | Precision | The number of digits |
---|---|---|
Float16
|
Semi-precision | 16 |
Float32
|
Single accuracy | 32 |
Float64
|
Doubles | 64 |
In addition, support for complex numbers and scores is based on these underlying data types. All underlying data types can be performed on each other without explicit type conversion through a flexible user-scalable type promotion system.
Use standard methods to represent text-based integers:
julia> 1
1
julia> 1234
1234
The default type of integer text depends on whether the target system is a 32-bit architecture or a 64-bit schema:
# 32-bit system:
julia> typeof(1)
Int32
# 64-bit system:
julia> typeof(1)
Int64
Julia 内部变量 `WORD_SIZE` 用以指示目标系统是 32 位还是 64 位.
# 32-bit system:
julia> WORD_SIZE
32
# 64-bit system:
julia> WORD_SIZE
64
In addition, Julia defines
Int
Uint
which are alias for the system-native signed and unsigned integer types, respectively:
# 32-bit system:
julia> Int
Int32
julia> Uint
Uint32
# 64-bit system:
julia> Int
Int64
julia> Uint
Uint64
For large integer text that cannot be represented by 32 bits but only 64 bits, it is always considered a 64-bit integer, regardless of the system type:
# 32-bit or 64-bit system:
julia> typeof(3000000000)
Int64
The inputs and outputs of unsigned
0x
0-9a-f
A-F
The size of the number of digits without a symbol, determined by the number of heteens:
julia> 0x1
0x01
julia> typeof(ans)
Uint8
julia> 0x123
0x0123
julia> typeof(ans)
Uint16
julia> 0x1234567
0x01234567
julia> typeof(ans)
Uint32
julia> 0x123456789abcdef
0x0123456789abcdef
julia> typeof(ans)
Uint64
Binary and octal text:
julia> 0b10
0x02
julia> typeof(ans)
Uint8
julia> 0o10
0x08
julia> typeof(ans)
Uint8
The minimum and maximum values of the underlying numeric type,
typemin
the
typemax
functions:
julia> (typemin(Int32), typemax(Int32))
(-2147483648,2147483647)
julia> for T = {Int8,Int16,Int32,Int64,Int128,Uint8,Uint16,Uint32,Uint64,Uint128}
println("$(lpad(T,7)): [$(typemin(T)),$(typemax(T))]")
end
Int8: [-128,127]
Int16: [-32768,32767]
Int32: [-2147483648,2147483647]
Int64: [-9223372036854775808,9223372036854775807]
Int128: [-170141183460469231731687303715884105728,170141183460469231731687303715884105727]
Uint8: [0,255]
Uint16: [0,65535]
Uint32: [0,4294967295]
Uint64: [0,18446744073709551615]
Uint128: [0,340282366920938463463374607431768211455]
The return
typemax
and
typemin
are of the same class as the given argument type. (
The above examples use some of the features that will be introduced, including
for loops,
strings,
and
interpolation.)
)
In Julia, an overflow occurs if the result of the calculation exceeds the maximum value that the data type can represent:
julia> x = typemax(Int64)
9223372036854775807
julia> x + 1
-9223372036854775808
julia> x + 1 == typemin(Int64)
true
As you can see, the arithmetic in Julia is actually an equal arithmetic. I
t reflects the underlying integer arithmetic characteristics of modern computers.
If an overflow is possible, be sure to explicitly check for
BigInt
type (see
Arithmetic for Arbitrary Precision).
To reduce the impact of overflows, integer addition and subtract, multiplication, and exponential operations promote the
Int
Uint
type.
(Division, residual, bit operations do not promote the type).
Divide error
The integer division
div
function) has two additional examples: divided by 0, and divided by the lowest negative
typemin
B
oth examples throw a
DivideError
The remainder and mode
rem
mod
throw a
DivideError
when their second argument is 0.
Floating points
Use a standard format to represent text-based floats:
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
The above results
Float64
values.
Text-based
Float32
can also be entered directly,
f
instead of
e
julia> 0.5f0
0.5f0
julia> typeof(ans)
Float32
julia> 2.5f-4
0.00025f0
Floating points can also be easily converted
Float32
julia> float32(-1.5)
-1.5f0
julia> typeof(ans)
Float32
The type of hete sixteen-point float can only be
Float64
julia> 0x1p0
1.0
julia> 0x1.8p3
12.0
julia> 0x.4p-1
0.125
julia> typeof(ans)
Float64
Julia also supports semi-accurate floats
Float16
but only for storage.
When calculated, they are converted
Float32
julia> sizeof(float16(4.))
2
julia> 2*float16(4.)
8.0f0
There are two zeros in the floating-point type, the zero of the positive number and the zero of the negative number.
They are equal, but have different binary notations, which can be seen
bits
function:
julia> 0.0 == -0.0
true
julia> bits(0.0)
"0000000000000000000000000000000000000000000000000000000000000000"
julia> bits(-0.0)
"1000000000000000000000000000000000000000000000000000000000000000"
There are three special standard floats:
Special values | Name | Describe | ||
Float16 | Float32 | Float64 | ||
Inf16 | Inft32 | Inf | Positive infinity | It's bigger than all the finite floats |
-Inf16 | -Inft32 | -Inf | Negative infinity | Smaller than all the finite floats |
NaN16 | NaN32 | NaN | Does not exist | Cannot compare size with any floating point (including its own) |
See Numerical comparison for details. According to the IEEE 754 standard, these values are available as follows:
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
typemin
typemax
also apply to floating-point types:
julia> (typemin(Float16),typemax(Float16))
(-Inf16,Inf16)
julia> (typemin(Float32),typemax(Float32))
(-Inf32,Inf32)
julia> (typemin(Float64),typemax(Float64))
(-Inf,Inf)
Most real numbers are not accurately represented by floats, so it is important to know the spacing between two adjacent floats, which is the accuracy of the computer.
Julia
eps
function that can be used
1.0
and the next representable float:
julia> eps(Float32)
1.1920929f-7
julia> eps(Float64)
2.220446049250313e-16
julia> eps() # same as eps(Float64)
2.220446049250313e-16
eps
function can also take floating points as arguments, giving the absolute difference between this value and the next representable floating
eps(x)
x
x + eps(x)
the next
x
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 the two adjacent floats is not fixed, the smaller the value, the smaller the spacing; I
n other words, floats are
0
and as values get larger and thinner, the distance between values grows exponentially.
By definition,
eps(1.0)
are the same as
eps(Float64)
1.0
64
float.
The
nextfloat
prevfloat
can be used to get the next or previous floating point:
julia> x = 1.25f0
1.25f0
julia> nextfloat(x)
1.2500001f0
julia> prevfloat(x)
1.2499999f0
julia> bits(prevfloat(x))
"00111111100111111111111111111111"
julia> bits(x)
"00111111101000000000000000000000"
julia> bits(nextfloat(x))
"00111111101000000000000000000001"
This example shows the number of floats adjacent to them and the represents of their binary integers.
If a number is not represented by an exact floating point, it needs to be rounded. Rounded models can be changed according to the IEEE 754 standard:
julia> 1.1 + 0.1
1.2000000000000002
julia> with_rounding(Float64,RoundDown) do
1.1 + 0.1
end
1.2
The default rounding model is
RoundNearest
which rounds to the nearest representable value, which uses as few valid numbers as possible.
There are many differences between the arithmetic of floating-point numbers and people's expectations, especially for those who do not understand the underlying implementation. M any books of scientific calculation explain these differences in detail. Here are some references:
To ensure the accuracy of integer and float calculations, Julia packaged GNU Multiple Precision Arithmetic Library,
GMP (https://gmplib.org/)
and GNU MPFR Library.
Julia provides
BigInt
and
BigFloat
You can construct between the
String
type or the String type:
julia> BigInt(typemax(Int64)) + 1
9223372036854775808
julia> BigInt("123456789012345678901234567890") + 1
123456789012345678901234567891
julia> BigFloat("1.23456789012345678901")
1.234567890123456789010000000000000000000000000000000000000000000000000000000004e+00 with 256 bits of precision
julia> BigFloat(2.0^66) / 3
2.459565876494606882133333333333333333333333333333333333333333333333333333333344e+19 with 256 bits of precision
julia> factorial(BigInt(40))
815915283247897734345611269596115894272000000000
However, the underlying data type and BigInt/BigFloat cannot be automatically typed and need to be explicitly specified:
julia> x = typemin(Int64)
-9223372036854775808
julia> x = x - 1
9223372036854775807
julia> typeof(x)
Int64
julia> y = BigInt(typemin(Int64))
-9223372036854775808
julia> y = y - 1
-9223372036854775809
julia> typeof(y)
BigInt (constructor with 10 methods)
The default precision of the BigFloat operation (the number of digits of a valid number) and the rounding model can be changed. The calculations then run according to the changed settings:
julia> with_rounding(BigFloat,RoundUp) do
BigFloat(1) + BigFloat("0.1")
end
1.100000000000000000000000000000000000000000000000000000000000000000000000000003e+00 with 256 bits of precision
julia> with_rounding(BigFloat,RoundDown) do
BigFloat(1) + BigFloat("0.1")
end
1.099999999999999999999999999999999999999999999999999999999999999999999999999986e+00 with 256 bits of precision
julia> with_bigfloat_precision(40) do
BigFloat(1) + BigFloat("0.1")
end
1.1000000000004e+00 with 40 bits of precision
Julia allows numeric text to be followed in front of the variable to represent multiplication. This helps write polynthic expressions:
julia> x = 3
3
julia> 2x^2 - 3x + 1
10
julia> 1.5x^2 - .5x + 1
13.0
Exponential functions also look better:
julia> 2^2x
64
Numerical text coefficients are the same as monolithic operators.
2^3x
resolved to
2^(3x)
2x^3
is resolved
2*(x^3)
Numeric text can also be used as a factor in parentheses expressions:
julia> 2(x-1)^2 - 3(x-1) + 1
3
Parenthesis expressions can be used as factors for variables:
julia> (x-1)x
6
Don't go on to write two variable parenthesis expressions, and don't put variables before parenthesis expressions. They cannot be used to refer to multiplication operations:
julia> (x-1)(x+1)
ERROR: type: apply: expected Function, got Int64
julia> x(x+1)
ERROR: type: apply: expected Function, got Int64
Both expressions are resolved as function calls: any expressions that are not numeric text, if followed by parentheses, represent the call function to handle the values in parentheses (see function for details). Therefore, both examples go wrong because the value on the left side is not a function.
It is important to note that there cannot be spaces between algege factors and variable or parenthesis expressions.
The text factor conflicts with two numeric expression syntax: heteagram integer text and floating-point text:
0xff
to numeric
0
times the
xff
1e10
resolved to numeric
1
the variable
e10
E
true of the E format.
In both cases, we parse the expression to numeric text:
0x
are parsed to hex text
e
E
and is resolved to floating-point text
Julia provides functions to get zeros and one text for a particular data type.
Function | Description |
---|---|
zero(x)
|
Text
x
the type of type
x
or variable x
|
one(x
|类型
the type
或变量
or variable x'
|
These two functions can be used in numeric comparison to avoid additional type conversions.
For example:
julia> zero(Float32)
0.0f0
julia> zero(1.0)
0.0
julia> one(Int32)
1
julia> one(BigFloat)
1e+00 with 256 bits of precision