
- Рейтинг Литрес:4.9
Полная версия:
Вадим Никитин Julia. Язык программирования. Быстрый старт
- + Увеличить шрифт
- - Уменьшить шрифт
4.0
При добавлении к выражению, вычисляющему значение, оператор :: читается как "является экземпляром". Его можно использовать в любом месте, чтобы утверждать, что значение выражения слева является экземпляром типа справа. Если тип справа конкретный, то значение слева должно иметь этот тип в качестве своей реализации. Если тип абстрактный, то достаточно, чтобы значение было реализовано конкретным типом, который является подтипом абстрактного типа. Если утверждение о типе не истинно, выбрасывается исключение, в противном случае возвращается левое значение.
Пример используемый выше, теперь нет нужды использовать комплексную форму записи:
julia> x::Complex{Float64}=-2
–2
julia> typeof(x)
ComplexF64 (alias for Complex{Float64})
julia> sqrt(x)
0.0 + 1.4142135623730951im
Когда оператор :: добавляется к переменной в левой части присваивания, он означает немного другое: он объявляет переменную всегда имеющей указанный тип, как объявление типа в статически типизированном языке, таком как C. Каждое значение, присвоенное переменной, будет преобразовано к объявленному типу с помощью функции convert(), если это возможно.
Целые числа
Типы целых чисел в Julia:

Целые числа вводятся и выводятся стандартным образом:
julia> 10
10
julia> 0123456789
123456789
Тип по умолчанию для целых чисел зависит от разрядности системы (64-бита):
julia> typeof(10)
Int64
julia> typeof(0123456789)
Int64
Julia также определяет типы Int и UInt, которые являются псевдонимами для системных знаковых и беззнаковых типов целых чисел соответственно:
julia> Int
Int64
julia> UInt
UInt64
Большие целые числа, которые не могут быть представлены с использованием 64 бит, но могут быть представлены в 128 битах, всегда создают 128-битные целые числа, независимо от типа системы:
julia> typeof(10000000000000000000)
Int128
Беззнаковые целые числа
Беззнаковые целые числа вводятся и выводятся с использованием префикса 0x и цифр от 0 до 9, а также латинских букв от a до f, используемых для обозначения шестнадцатеричных чисел, использование заглавных букв A-F также допустимо. Размер беззнакового значения определяется количеством используемых шестнадцатеричных цифр:
julia> x = 0x1
0x01
julia> typeof(x)
UInt8
julia> x = 0x123
0x0123
julia> typeof(x)
UInt16
julia> x = 0x1234567
0x01234567
julia> typeof(x)
UInt32
julia> x = 0x123456789abcdef
0x0123456789abcdef
julia> typeof(x)
UInt64
julia> x = 0x11112222333344445555666677778888
0x11112222333344445555666677778888
julia> typeof(x)
UInt128
Значения, слишком большие для типов Int128, UInt128, при вводе получат специальный тип BigInt:
julia> typeof(100000000000000000000000000000000000000)
Int128
julia> typeof(1000000000000000000000000000000000000000)
BigInt
julia> typeof(0xffffffffffffffffffffffffffffffff)
UInt128
julia> typeof(0xfffffffffffffffffffffffffffffffff)
BigInt
Это не беззнаковый тип, но это единственный встроенный тип, достаточно большой для представления таких больших целых значений.
Поведение при переполнении
В Julia превышение максимального представляемого значения данного типа приводит к циклическому поведению. Пример (функции typemax(), typemin(), возвращают максимальное и минимальное значения для заданного типа, == оператор равенства):
julia> x = typemax(Int64)
9223372036854775807
julia> x+1
–9223372036854775808
julia> x + 1 == typemin(Int64)
true
julia> x = typemax(UInt64)
0xffffffffffffffff
julia> x+1
0x0000000000000000
julia> x + 1 == typemin(UInt64)
true
В тех случаях, когда переполнение возможно, рекомендуется производить проверку на цикличное поведение. В противном случае используйте тип BigInt арифметики произвольной точности. Ниже приведен пример поведения при переполнении и как его можно решить с помощью BigInt():
julia> 10^19
–8446744073709551616
julia> BigInt(10)^19
10000000000000000000
Числа с плавающей точкой
Типы чисел с плавающей точкой в Julia:

Числа с плавающей точкой вводятся и выводятся стандартным образом:
julia> 1.0
1.0
julia> 1.
1.0
julia> 0.5
0.5
julia> .5
0.5
julia> -1.23
–1.23
При необходимости можно использовать E-нотацию:
julia> 1e10
1.0e10
julia> 2.5e-4
0.00025
Все результаты из примеров выше имеют тип Float64 (тип по умолчанию). Если вы хотите ввести значение с типом Float32, то необходимо использовать f вместо e следующим образом:
julia> x = 0.5f0
0.5f0
julia> typeof(x)
Float32
julia> 2.5f-4
0.00025f0
Значение с типом Float16:
julia> Float16(4.)
Float16(4.0)
julia> 2*Float16(4.)
Float16(8.0)
Ноль с плавающей точкой
Числа с плавающей точкой имеют два нуля – положительный нуль и отрицательный нуль. Они равны друг другу, но имеют разные двоичные представления, что можно увидеть с помощью функции bitstring(), которая дает буквальное битовое представление примитивного типа:
julia> 0.0 == -0.0
true
julia> bitstring(0.0)
"0000000000000000000000000000000000000000000000000000000000000000"
julia> bitstring(-0.0)
"1000000000000000000000000000000000000000000000000000000000000000"
Когда точности или размерности Float64 недостаточно, можно использовать специальный тип BigFloat:
julia> 2.0^100/4
3.1691265005705735e29
julia> BigFloat(2.0)^100/4
3.16912650057057350374175801344e+29
BigFloat знаковый тип арифметики произвольной точности, не назначаемый автоматически при вводе, а требующий явного объявления для использования.
Функции минимального и максимального значений для типов также применимы:
julia> (typemin(Float16),typemax(Float16))
(-Inf16, Inf16)
julia> (typemin(Float32),typemax(Float32))
(-Inf32, Inf32)
julia> (typemin(Float64),typemax(Float64))
(-Inf, Inf)
Результатом будут специальные значения – отрицательная и положительная бесконечности. Значения чисел превышающих числовой диапазон типа также будут заменены на специальные значения:
julia> 4.2^1000
Inf
julia> -4.2^1000
–Inf
Специальные значения
Существует три определенных стандартных значения с плавающей точкой, которые не соответствуют ни одной точке на линии вещественных чисел:

По стандарту IEEE 754, эти значения с плавающей точкой являются результатами определенных арифметических операций:
julia> 1/0
Inf
julia> -5/0
–Inf
julia> 0.000001/0
Inf
julia> 0/0
NaN
julia> 1/Inf
0.0
julia> 1/-Inf
–0.0
julia> -1/Inf
–0.0
julia> -1/-Inf
0.0
julia> 500 + Inf
Inf
julia> 500 – Inf
–Inf
julia> Inf + Inf
Inf
julia> -Inf -Inf
–Inf
julia> Inf – Inf
NaN
julia> Inf * Inf
Inf
julia> Inf*-Inf
–Inf
julia> -Inf * -Inf
Inf
julia> Inf / Inf
NaN
julia> Inf /-Inf
NaN
julia> -Inf /Inf
NaN
julia> -Inf /-Inf
NaN
julia> 0 * Inf
NaN
julia> 0 *-Inf
NaN
Тип NaN
NaN не равно, не меньше и не больше чего-либо, включая самого себя:
julia> NaN == NaN
false
julia> NaN != NaN
true
julia> NaN < NaN
false
julia> NaN > NaN
false
Это может вызвать проблемы, например при работе с массивами:
julia> [1 NaN] == [1 NaN]
false
Функции Julia для работы со специальными значениями:

Функция isequal() считает NaNs равными друг другу:
julia> isequal(NaN, NaN)
true
julia> isequal([1 NaN], [1 NaN])
true
julia> isequal(NaN, NaN32)
true
Функцию isequal() можно также использовать для различения знаковых нулей:
julia> -0.0 == 0.0
true
julia> isequal(-0.0, 0.0)
false
Машинный эпсилон
Большинство реальных чисел не могут быть точно представлены числами с плавающей точкой, поэтому для многих целей важно знать расстояние между двумя соседними представляемыми числами с плавающей точкой, которое часто называют машинным эпсилоном.
Функция eps() в Julia дает расстояние между 1.0 и следующим большим значением с плавающей точкой, при использовании в качестве аргумента типа числа с плавающей точкой:
julia> eps(Float16)
Float16(0.000977)
julia> eps(Float32)
1.1920929f-7
julia> eps(Float64)
2.220446049250313e-16
julia> eps(BigFloat)
1.727233711018888925077270372560079914223200072887256277004740694033718360632485e-77
Функция eps также может принимать в качестве аргумента значение с плавающей точкой, и выдавать абсолютную разницу между этим значением и следующим представимым значением с плавающей точкой. Другими словами, eps(x) выдает значение того же типа, что и x, такое, что x + eps(x) является следующим представимым значением с плавающей точкой, большим, чем 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
Расстояние между двумя соседними представляемыми числами с плавающей точкой не является постоянным, оно меньше для меньших значений и больше для больших значений. Другими словами, представляемые числа с плавающей запятой наиболее плотно расположены на линии вещественных чисел вблизи нуля и становятся более редкими экспоненциально по мере удаления от нуля. По определению, eps(1.0) – это то же самое, что eps(Float64), поскольку 1.0 – это 64-битное значение с плавающей точкой.
Если число не имеет точного представления с плавающей точкой, оно будет округлено до соответствующего представляемого значения. По умолчанию Julia использует режим округления, называемый RoundNearest. Он округляет до ближайшего целого числа, а ничьи округляются до ближайшего четного целого числа.
Базовые операторы Julia
Следующие арифметические операторы поддерживаются для всех примитивных числовых типов:

Несколько простых примеров с использованием арифметических операторов:
julia> 1+10-5
6
julia> 2-6
–4
julia> 5*20/10
10.0
julia> 20\10
0.5
julia> 3^3 27
julia> 5.5%-2
1.5
Число, помещенное непосредственно перед идентификатором или круглыми скобками, например, 2x или 2(x+y), рассматривается как умножение.
Логические операторы
Для типов Bool поддерживаются следующие логические операторы:

Примеры использования логических операторов:
julia> !true
false
julia> !false
true
julia> true && true
true
julia> true && false
false
julia> false && false
false
julia> true || true
true
julia> true || false
true
julia> false || false
false
Побитовые операторы
Следующие побитовые операторы поддерживаются для всех примитивных целочисленных типов:

julia> ~100
–101
julia> 121 & 232
104
julia> 121 | 232
249
julia> 121 ⊻ 232 #Знак юникода
145
julia> xor(121, 232)
145
julia> ~UInt32(121)
0xffffff86
julia> ~UInt8(121)
0x86
Операторы обновления
Каждый арифметические и побитовый оператор имеет обновляющую версию, которую можно сформировать, поставив знак равенства (=) сразу после оператора. Этот оператор обновления присваивает результат операции обратно своему левому операнду.
Версии всех двоичных арифметических и побитовых операторов:

Пример использования операторов обновления:
julia> x = 25
25
julia> x += 25
50
julia> x
50
Оператор обновления переопределяет переменную в левой части. В результате тип переменной может измениться:
julia> x = 0x01
0x01
julia> typeof(x)
UInt8
julia> x *= 2
2
julia> typeof(x)
Int64
Векторизированные “точечные” операторы
Для каждого бинарного оператора существует соответствующий "точечный" оператор, который применяет оператор поэлементно над многоэлементными структурами (массивы и т.п.).
Примеры использования “точечного” оператора:
julia> [2, 4 ,6].^2
3-element Vector{Int64}:
4
16
36
julia> x=[1 2 3 4 5 ; 6 7 8 9 10]
2×5 Matrix{Int64}:
1 2 3 4 5
6 7 8 9 10
julia> x.+1
2×5 Matrix{Int64}:
2 3 4 5 6
7 8 9 10 11
julia> x
2×5 Matrix{Int64}:
1 2 3 4 5
6 7 8 9 10
julia> x .+=1
2×5 Matrix{Int64}:
2 3 4 5 6
7 8 9 10 11
julia> x
2×5 Matrix{Int64}:
2 3 4 5 6
7 8 9 10 11
Обратите внимание, "точечные" операторы обновления изменяют исходные значения, в отличии от остальных, создающих новые.
Операторы сравнения
Для всех примитивных числовых типов определены стандартные операции сравнения:

Пример использования операторов сравнения:
julia> 2 == 2.0
true
julia> 3 == 5
false
julia> 3 != 5
true
julia> 3 < 5
true
Целочисленные числа сравниваются стандартным образом – путем сравнения битов. Числа с плавающей точкой сравниваются в соответствии со стандартом IEEE 754:
Конечные числа упорядочиваются обычным образом.
Положительный ноль равен, но не больше отрицательного нуля.
Inf равно самому себе и больше, чем все остальные, кроме NaN.
–Inf равно самому себе и меньше всех остальных, кроме NaN.
NaN не равно, не меньше и не больше ничего, включая самого себя.
Использование "точечных" операторов сравнения для многоэлементных структур возвращает булев массив с результатами сравнения для каждого элемента:
julia> [1,2,3,4,5].<= 3
5-element BitVector:
1
1
1
0
0
Сравнения в Julia можно объединять в цепочки:
julia> 10 < 15 <= 20 < 30 == 30 > 20 >= 10 == 10 < 30 != 5
true
julia> x=[1 2 3 4 5 ; 6 7 8 9 10]
2×5 Matrix{Int64}:
1 2 3 4 5
6 7 8 9 10
julia> 1 .< x .< 7
2×5 BitMatrix:
0 1 1 1 1
1 0 0 0 0
Приоритет и ассоциативность операторов
Julia применяет следующий порядок и ассоциативность операций, от высшего к низшему:

Числовые коэффициенты, например, 2x, рассматриваются как умножение с более высоким старшинством, чем любая другая двоичная операция, за исключением ^, где они имеют старшинство только как экспонента:
julia> x = 3
3
julia> 2x^2
18
julia> 2^2x
64
Базовые функции
Julia поддерживает три формы числового преобразования, которые отличаются друг от друга обработкой неточных преобразований:
Записи вида T(x) или convert(T,x) преобразуют x в значение типа T. Результат зависит от следующих двух случаев:
● Если T – тип с плавающей точкой, то результатом будет ближайшее представимое значение, которое может быть положительной или отрицательной бесконечностью.
● Если T является целочисленным типом, и x не может быть представлен в типе T (наличие значащих цифр после запятой или переполнение типа Т), то возникает ошибка InexactError.
Запись вида x%T преобразует целое число x в значение целочисленного типа T, соответствующее x по модулю 2^n. Здесь n представляет количество битов в T. Другими словами, двоичное представление усекается, чтобы оно соответствовало размеру. Применимо только для целых чисел и целочисленных типов, переполнение типа обрабатывается стандартно.
Конец ознакомительного фрагмента.
Текст предоставлен ООО «Литрес».
Прочитайте эту книгу целиком, купив полную легальную версию на Литрес.
Безопасно оплатить книгу можно банковской картой Visa, MasterCard, Maestro, со счета мобильного телефона, с платежного терминала, в салоне МТС или Связной, через PayPal, WebMoney, Яндекс.Деньги, QIWI Кошелек, бонусными картами или другим удобным Вам способом.