0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Julia】 基礎: 型

Last updated at Posted at 2023-03-26

0. はじめに

本稿では Julia の型を概説します.

Julia では型は Core.typeof() で,要素の型は Base.eltype() で見ることができます.

@show typeof("1"), typeof(1)
# (typeof("1"), typeof(1)) = (String, Int64)
@show eltype(["1", "one", "Eins", "un", "ひ", "一"])
# String

型の包含関係は <: です.

help?> <:
search: <:

  <:(T1, T2)

  Subtype operator: returns true if and only if all values of type T1 are also
  of type T2.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> Float64 <: AbstractFloat
  true
  
  julia> Vector{Int} <: AbstractArray
  true
  
  julia> Matrix{Float64} <: Matrix{AbstractFloat}
  false

1. 整数型 Integer

help?> Integer
search: Integer isinteger

  Integer <: Real

  Abstract supertype for all integers.

1.1 Int64

数値計算する上でまず覚えるとよい型は 64ビット符号付き整数型 Int64 です.
Int はそのエイリアスです.
全部で Int8 Int64 Int32 Int16 Int128 というビット数の異なる符号付き整数型があります.

Int64 <: Signed <: Integer# true
Int == Int64# true
Int8 <: Int64# false
typemax(Int64) == 2^63 - 1# true

Integers and Floating-Point Numbers · The Julia Language

1.2 BigInt

BigInt 型は桁数の制限がほとんどないので大きな整数の計算に使えます.

#%% BigInt
BigInt <: Signed <: Integer# true
Int64 <: BigInt# false
# ERROR: MethodError: no method matching typemax(::Type{BigInt})
# typemax(BigInt)
2^63# -9223372036854775808
big(2)^63# 9223372036854775808
googol = big(10)^100# 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Exponent やメモリのオーバーフローには気をつけましょう.

try
    googolplex = big(10)^googol
catch y
    if isa(y, OverflowError)
        @error "To think googolplex might be absurd!"
    end
end
println("Googolplex is not Googleplex.")
┌ Error: To think googolplex might be absurd!
└ @ Main ~/.. 
Googolplex is not Googleplex.

BigFloats and BigInts

1.3 ブール型 Bool

Bool 型はプログラミング一般において最も重要な概念のひとつです.
Julia では true or false の2値です.

help?> Bool
search: Bool BoundsError

  Bool <: Integer

  Boolean type, containing the values true and false.

  Bool is a kind of number: false is numerically equal to 0 and true is
  numerically equal to 1. Moreover, false acts as a multiplicative "strong
  zero":

  julia> false == 0
  true
  
  julia> true == 1
  true
  
  julia> 0 * NaN
  NaN
  
  julia> false * NaN
  0.0

  See also: digits, iszero, NaN.


2元 Boole 束の演算を計算することができる他,整数としての計算もできます.
== が返す値のタイプも Bool ですので極論これが分かっていないとコーディングできません.

Bool <: Integer# true
typeof(true)# Bool
true & false# false
true | false# true
true + false# 1
typeof(true + 0)# Int64
################
if 1 == 1 && 0 == 1
    println("Zero equals one.")
else
    @show 0 == 1
end
# 0 == 1 = false

2. 浮動小数点数型 AbstractFloat

Float64 <: AbstractFloat

  64-bit floating point number type (IEEE 754 standard).

  Binary format: 1 sign, 11 exponent, 52 fraction bits.

2.1 Float64

Julia で倍精度浮動小数点数を表す型は Float64 です.

浮動小数点数型 には Float64 Float32 Float16 があります.

float で浮動小数点数型に変換できます.
詳しくは help?> float (REPL で ?) にあります.
0.0 の表記などほかは C/C++ に似ています.

float(1)# 1.0
typeof(float(1))# Float64
typeof(1 / 2)# Float64
typeof(0.0)# Float64
typeof(1 + 0.0)# Float64
floatmax()# 1.7976931348623157e308

いわゆる最大値は typemax ではなく floatmax で出力します.

help?> floatmax
search: floatmax floatmin

  floatmax(T = Float64)

  Return the largest finite number representable by the floating-point type T.

  See also: typemax, floatmin, eps.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> floatmax(Float16)
  Float16(6.55e4)
  
  julia> floatmax(Float32)
  3.4028235f38
  
  julia> floatmax()
  1.7976931348623157e308
  
  julia> typemax(Float64)
  Inf

2.2 BigFloat

Bigfloat を使うと桁数が増えます.

BigFloat(pi)# 3.141592653589793238462643383279502884197169399375105820974944592307816406286198
BigFloat(1.0)# 1.0
BigFloat(1.25)# 1.25
BigFloat(1.1)# 1.100000000000000088817841970012523233890533447265625
BigFloat("1.1")# 1.100000000000000000000000000000000000000000000000000000000000000000000000000003

BigFloats and BigInts

3. 有理数型 Rational

有理数型 Rational は主に浮動小数点数型にせずに分数計算したいときに用いられ,数値計算では非常に重要な意味を持っています.


Python とくに Sympy で計算したことがある人は任意精度計算(および有理数計算)の意義はおわかりのことと思います.

除算 // を使います.
div()/ は有理数体の演算ではありません.
div() は整数の除算で / は浮動小数点演算として解釈されます.

typeof(1 // 2)# Rational{Int64}
typeof(1 // (big(5)^31 * 31))# Rational{BigInt}

div(1,2), typeof(div(1,2))# (0, Int64)
div(-3,2)# -1
typeof(1 / 2)# Float64
help?> div
search: div divrem DivideError splitdrive code_native @code_native

  div(x, y)
  ÷(x, y)

  The quotient from Euclidean (integer) division. Generally equivalent to a
  mathematical operation x/y without a fractional part.
...
help?> /
search: / //

  /(x, y)

  Right division operator: multiplication of x by the inverse of y on the
  right. Gives floating-point results for integer arguments.
...

4. 複素数型 Complex

Julia では虚数単位 $i$ は im です.1

typeof(im)# Complex{Bool}
typeof(1im)# Complex{Int64}
typeof(1.0im)# ComplexF64 (alias for Complex{Float64})
complex(1)# 1 + 0im
complex(1,1)# 1 + 1im
(1 + 1im)^2#0 + 2im

Complex 型は Real から構成されるという観点が取られており かつ Real 型は包含していません.

Real <: Complex# false
help?> Complex
search: Complex complex ComplexF64 ComplexF32 ComplexF16 precompile

  Complex{T<:Real} <: Number

  Complex number type with real and imaginary part of type T.

  ComplexF16, ComplexF32 and ComplexF64 are aliases for Complex{Float16},
  Complex{Float32} and Complex{Float64} respectively.

  See also: Real, complex, real.

5. 文字列型 String

String 型の「空(くう)文字」は string() で与えることができます.
文字列への変換も string() です.
文字列の結合は * です.+ では行えません.

string()# ""
string(1)# "1"
"Albert" * " Einstein"# "Albert Einstein"
# ERROR: MethodError: no method matching +(::String, ::String)
# "Albert" + " Einstein"
  • 文字列は添字を取れます.
"Bill Evans"[end]
# 's': ASCII/Unicode U+0073 (category Ll: Letter, lowercase)
  • 繰り返しは repeat()^ です.
repeat("So what? ", 4)
"So what? " ^ 4
# "So what? So what? So what? So what? "
  • 応用してみましょう.
DRA = "Don't run away"
line1 = DRA * " now... "
line2 = (DRA * ", ")^3 * DRA * "!"
line1 * line2
# "Don't run away now... Don't run away, Don't run away, Don't run away, Don't run away!"
  • 文字列は for 文の宣言で使えます.
for Rhapsody in "Blue"
    print(Rhapsody)
    if Rhapsody == "Blue"[end]
        break
    end
    print("✰")
end
# B✰l✰u✰e
  • プロットなどで $\LaTeX$ 式の数式が出したければ LaTeXStrings パッケージを宣言して文字列の前に L と書きます.
using LaTeXStrings
L"x \\mathrm{[m]}"# L"$x \\mathrm{[m]}$"

6. 集合型 Set

空集合は以下で書きます.小文字の s では書けません.

Set([])# Set{Any}()

要素の追加は push!() です.2
! は破壊的変更の印です.

begin
     = Set{Int64}([])
    @show isempty()
    push!(, 1)
    @show 
end

出力:

isempty(∅) = true
∅ = Set([1])
Set{Int64} with 1 element:
  1
  • 合併は union() です.
println(union(Set([1,2,3]), Set([3,4,5])))
# Set([5, 4, 2, 3, 1])

7. Array 型

Set と異なり Array は順序が全て決まっています.
空列は以下です.

[]# Any[]
Any[]# Any[]

7.1 ベクトル型 Vector

Julia では VectorArray{T,1} のエイリアスです.

数学的にはベクトルの成分表示に対応しています.
Julia の Vector はそれに加えて Python の listnp.array のようにも使います.

help?> Vector
search: Vector BitVector DenseVector StridedVector AbstractVector

  Vector{T} <: AbstractVector{T}

  One-dimensional dense array with elements of type T, often used to represent
  a mathematical vector. Alias for Array{T,1}.
  • 空のベクトルは以下のように指定します.
Vector{Float64}()# Float64[]
Float64[]# Float64[]

型指定(型注釈)では ::Vector{Float64} などと書きます.

julia> typeof(Vector{Float64}())
Vector{Float64} (alias for Array{Float64, 1})
  • 要素の型の変換が行えます.
[1,2,3]
#=
3-element Vector{Int64}:
 1
 2
 3
=#
v = Vector{Float64}([1,2,3])
#=
3-element Vector{Float64}:
 1.0
 2.0
 3.0
=#
  • 要素の追加は push!() で行います.
println(push!(Vector{Float64}([1,2,3]), 4.1))
# [1.0, 2.0, 3.0, 4.1]
  • append!() は要素の追加ではなく配列の結合です.
println(append!([1,2,3], [3,4,5]))
# [1, 2, 3, 3, 4, 5]

他の関数については Collections and Data Structures · The Julia Language をご覧下さい.

7.2 行列型 Matrix

Julia では MatrixArray{T,2} のエイリアスです.

行列は数学的には2次元的な数列なのでこれは正しいです.3

help?> Matrix
search: Matrix BitMatrix DenseMatrix StridedMatrix AbstractMatrix

  Matrix{T} <: AbstractMatrix{T}

  Two-dimensional dense array with elements of type T, often used to represent
  a mathematical matrix. Alias for Array{T,2}.

計算の具体例です.

A = [1 2; 3 4im]
2×2 Matrix{Complex{Int64}}:
 1+0im  2+0im
 3+0im  0+4im
  • エルミート共役
A'
2×2 adjoint(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:
 1+0im  3+0im
 2+0im  0-4im
  • 行列の代数演算でエルミート行列を作る
(A + A') / 2
2×2 Matrix{ComplexF64}:
 1.0+0.0im  2.5+0.0im
 2.5+0.0im  0.0+0.0im

8. 辞書型 Dict

help?> Dict
search: Dict TypeDict IdDict WeakKeyDict SubtypeDict AbstractDict MakeTypeDict

  Dict([itr])

  Dict{K,V}() constructs a hash table with keys of type K and values of type
  V. Keys are compared with isequal and hashed with hash.

  Given a single iterable argument, constructs a Dict whose key-value pairs
  are taken from 2-tuples (key,value) generated by the argument.

8.1 辞書を使う

辞書型の宣言を Julia で行うには Dict() を使います.

対応の始め,いわば辞典の単語を key といい,対応の終わり,いわば単語の意味を value といいます.
比喩の部分は個々の事例ごとに「人の名前と試験の点数」などになったりします.
Array と異なるのはこの対応の関係です.

辞書への追加は模式的には Dictionary["key"] = value のように行えます.4 5

push!() でもできます.

begin
    D = Dict{String, String}([])
    D["author"] = "Aristotle"
    push!(D, "A" => "Any")
    @show D
end
# D = Dict("A" => "Any", "author" => "Aristotle")

辞書は類を作るのに役立ちます.
例えば本当の辞書や索引のように 頭文字のアルファベットによる類別を書いてみましょう.

シングルクォーテーションマーク ' は特別なタイプ Char を用意します.6 7

Dict('A' => Set(["Alain Aspect", "Antonín Dvořák"]))
# Dict{Char, Set{String}} with 1 entry:...

8.2 辞書の応用

次にこの手法を応用してみましょう.
類のタイプを Set から Vector に変え,更に内包の for のベクトルから辞書を作ってみます.

Dict([(alphabet, Vector{Type}([])) for alphabet in 'A':'Z'])
# Dict{Char, Vector{Type}} with 26 entries:...

このようなやり方で,型のすべてのサブタイプを格納する辞書を作ってみましょう.

#%% application of a dictionary
function nextsubtype!(T, V)# recurrence
    push!(V, T)
    for t in subtypes(T)
        nextsubtype(t, V)
    end
    # ref. https://en.wikibooks.org/wiki/Introducing_Julia/Types
end
function allsubtypes(T)# vector of types
    V = Vector{Type}()
    nextsubtype!(T, V)
    return V
end
function SubtypeDict(T)
    X = allsubtypes(T)# vector of types
    S = Set([string(x)[1] for x in X])# alphabets
    DictOfTypes = Dict([(s, Vector{Type}([])) for s in S])
    for x in X
        push!(DictOfTypes[string(x)[1]], x)
    end
    return DictOfTypes
end
T = Number
_ans = SubtypeDict(T)
display(_ans)

open("SubtypeDict" * string(T) * ".txt", "w") do f
    write(f, repr("text/plain", _ans))
end

display の結果は text データとして保存すれば環境に依存せず全体をそのまま見ることができます.8 9

Dict{Char, Vector{Type}} with 9 entries:
  'B' => [BigFloat, Bool, BigInt]
  'F' => [Float16, Float32, Float64]
  'U' => [Unsigned, UInt128, UInt16, UInt32, UInt64, UInt8]
  'A' => [AbstractFloat, AbstractIrrational]
  'I' => [Irrational, Integer, Int128, Int16, Int32, Int64, Int8]
  'R' => [Real, Rational]
  'S' => [Signed]
  'N' => [Number]
  'C' => [Complex]

ソートしたい場合は以下のようにします.10

sort(collect(_ans), by = x->x[1])
9-element Vector{Pair{Char, Vector{Type}}}:
 'A' => [AbstractFloat, AbstractIrrational]
 'B' => [BigFloat, Bool, BigInt]
 'C' => [Complex]
 'F' => [Float16, Float32, Float64]
 'I' => [Irrational, Integer, Int128, Int16, Int32, Int64, Int8]
 'N' => [Number]
 'R' => [Real, Rational]
 'S' => [Signed]
 'U' => [Unsigned, UInt128, UInt16, UInt32, UInt64, UInt8]

_ans は引き継がれています.

9. 型をもっと学ぶ*

9.1 Abstract Types*

型の包含関係を見て Julia の理解を含めましょう.
例えば RationalReal の直下にあってサブタイプを持ちません.

supertype(Rational)# Real
subtypes(Rational)# Type[]

RealNumber の直下にあります.

subtypes(Number)# 2-element Vector{Any}:
2-element Vector{Any}:
 Complex
 Real

すべてのタイプの上には Any があります.

subtypes(Any)# 611-element Vector{Any}: (Default)
supertype(Any)# Any 

9.2 型のグラフを書く**

型の全貌をグラフにしてみましょう.
Any の自己ループを除けばグラフは木 (tree) になるはずで再帰的に書いています.

Github に入れた typetree.jl

主要部は以下です.

typetree.jl
function showtypetree(T, io, level=0, tab=8)
    ladder = "ᴸ" * repeat("-", 3)
    ...
    println(T)
    write(io, string(T) * "\n")
    for t in subtypes(T)
        showtypetree(t, io, level+1)# recurrence
    end
    # https://en.wikibooks.org/wiki/Introducing_Julia/Types
end

2行目は鍵型の字は Unicode の中から中央の L を選びました.11

  • 結果を保存したレポジトリです.
    Krypf/20230320Qiita: Julia basics

  • 9割は Function のサブタイプです.using などでパッケージを入れるともっと増えます.

Number の例を挙げましょう.

Number
	ᴸ---Complex
	ᴸ---Real
		ᴸ---AbstractFloat
			ᴸ---BigFloat
			ᴸ---Float16
			ᴸ---Float32
			ᴸ---Float64
		ᴸ---AbstractIrrational
			ᴸ---Irrational
		ᴸ---Integer
			ᴸ---Bool
			ᴸ---Signed
				ᴸ---BigInt
				ᴸ---Int128
				ᴸ---Int16
				ᴸ---Int32
				ᴸ---Int64
				ᴸ---Int8
			ᴸ---Unsigned
				ᴸ---UInt128
				ᴸ---UInt16
				ᴸ---UInt32
				ᴸ---UInt64
				ᴸ---UInt8
		ᴸ---Rational

10. おわりに

Julia における型を学びました.
Julia は Python と同じく動的型付け言語です.しかし Python とは異なり Julia では TypeError に対処する機会が多くあります.
従って型の理解は必ず身につけて置かなければなりません.


この制約は一見枷のようにも思えます.でもこうした枠 (組み) が却ってコードの方向性や速度に寄与し決定することもあるのではないでしょうか.
譬えれば言語にはこんな特性があります:12 13

  • C/C++ (/C#), レールの上をひた走る鉄道.速い.でも同じ街の中を移動するのには必要ない.
  • Python, バスや自家用車といった車.既製品 (パッケージ) 多数.拡張性◎.鉄道よりは遅い.
  • MATLAB, ヘリコプター.構造 (構文) は簡単.操縦 (ファイル管理) が面倒.特定の導線 (線型代数) では高速.ヘリポートが必要.(客として)簡単に乗れない.
  • Julia, (自家用) 飛行機.海外に行くにはとても速い.滑走路が必要.国内移動程度なら C/C++ で足りることもある.用途を選ぶ.空港 (パッケージ) がない地域も多い.

このように,Julia は C 系言語よりは制約はある種少ない上に,Python より激烈に速く,(比喩を離れて) 実際上は Python/MATLAB からの移行の学習コストはほぼ0に等しいわけです.

また C 系の (言語で食べてきた) プログラマ(エンジニア)が喧伝するほどに静的型付けの絶対性に固執する必要もないと僕は思いますし,だからこそ型をある時は堅固ある時は柔軟に扱える動的型付け言語 Julia は高速な数値計算ツールとして最強なのです.

つまり Julia は,プログラムの実行速度の観点からは Python と (ここが大きい),構文の簡明さの観点からは C/C++ と,アクセシビリティの観点からは MATLAB と,互いに補い合える関係にあるということなのです.


(参考)

  1. Python では 1j です.

  2. 古いページでは push!() は遅いと書かれているときもありますが現在のバージョン Julia Version 1.8.5 では自分で変なことを考えるよりも for 文と push!() の方が速いコードもあります.

  3. 数列は写像として定義する場合とその値として定義する場合があります.

  4. Julia早引きノート[15]辞書(dictionary) - Qiita

  5. Julia言語のBase.Dictコレクションで連想配列を扱う方法

  6. How to create strings combining all letters? - General Usage - Julia Programming Language

  7. Generate all words of a given size from a fixed alphabet - General Usage - Julia Programming Language

  8. I/O and Network · The Julia Language

  9. Strings · The Julia Language

  10. How do I sort a dictionary by its keys? - New to Julia - Julia Programming Language

  11. Unicode Input · The Julia Language

  12. 言語特性の譬え話は昔からあります.Fortran は第3世代最強の呼び声高いプテラ (かせきポケモン) です.18のプログラミング言語をポケモンに例えてみた! | TechAcademyマガジン

  13. 譬え話で観るブラウザ戦争.納得?5つのブラウザを乗り物で表現すると…:らばQ

0
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?