Integers and Floating-Point Numbers

整数と浮動小数点値は、算術と計算の基本的な構成要素です。このような値の組み込み表現は数値プリミティブと呼ばれ、コード内での整数および浮動小数点数の即値としての表現は数値リテラルとして知られています。たとえば、1は整数リテラルであり、1.0は浮動小数点リテラルです。オブジェクトとしてのそれらのバイナリのメモリ内表現は数値プリミティブです。

Juliaは幅広い原始的な数値型を提供しており、算術演算子やビット演算子、標準的な数学関数がそれらに対して定義されています。これらは、現代のコンピュータでネイティブにサポートされている数値型や演算に直接マッピングされるため、Juliaは計算リソースを最大限に活用することができます。さらに、JuliaはArbitrary Precision Arithmeticのソフトウェアサポートを提供しており、ネイティブハードウェア表現では効果的に表現できない数値に対する演算を処理できますが、その分、比較的遅いパフォーマンスが求められます。

以下はジュリアの基本的な数値型です:

  • 整数型:
TypeSigned?Number of bitsSmallest valueLargest value
Int88-2^72^7 - 1
UInt8802^8 - 1
Int1616-2^152^15 - 1
UInt161602^16 - 1
Int3232-2^312^31 - 1
UInt323202^32 - 1
Int6464-2^632^63 - 1
UInt646402^64 - 1
Int128128-2^1272^127 - 1
UInt12812802^128 - 1
BoolN/A8false (0)true (1)
  • 浮動小数点型:
TypePrecisionNumber of bits
Float16half16
Float32single32
Float64double64

さらに、Complex and Rational Numbers の完全なサポートは、これらの基本的な数値型の上に構築されています。すべての数値型は、柔軟でユーザー拡張可能な type promotion system により、明示的なキャスティングなしで自然に相互運用します。

Integers

リテラル整数は標準的な方法で表現されます:

julia> 1
1

julia> 1234
1234

整数リテラルのデフォルトタイプは、ターゲットシステムが32ビットアーキテクチャか64ビットアーキテクチャかによって異なります:

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

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

Juliaの内部変数 Sys.WORD_SIZE は、ターゲットシステムが32ビットか64ビットかを示します:

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

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

Juliaはまた、システムの符号付きおよび符号なしのネイティブ整数型のエイリアスであるIntUIntの型を定義しています。

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

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

32ビットでは表現できないが64ビットでは表現できる大きな整数リテラルは、システムのタイプに関係なく常に64ビット整数を生成します。

# 32-bit or 64-bit system:
julia> typeof(3000000000)
Int64

符号なし整数は、0x プレフィックスと16進数(基数16)数字 0-9a-f を使用して入力および出力されます(大文字の数字 A-F も入力に使用できます)。符号なし値のサイズは、使用される16進数の桁数によって決まります:

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

この動作は、整数値に対して符号なしの16進数リテラルを使用する際、通常は単なる整数値ではなく、固定された数値のバイトシーケンスを表すために使用されるという観察に基づいています。

バイナリおよび8進数リテラルもサポートされています:

julia> x = 0b10
0x02

julia> typeof(x)
UInt8

julia> x = 0o010
0x08

julia> typeof(x)
UInt8

julia> x = 0x00000000000000001111222233334444
0x00000000000000001111222233334444

julia> typeof(x)
UInt128

16進数リテラルに関して、2進数および8進数リテラルは符号なし整数型を生成します。バイナリデータ項目のサイズは、リテラルの先頭の桁が 0 でない場合、必要な最小サイズです。先頭にゼロがある場合、サイズは、同じ長さで先頭の桁が 1 のリテラルに対して必要な最小サイズによって決まります。つまり、次のことを意味します:

  • 0x10x12UInt8 リテラルです、
  • 0x1230x1234UInt16 リテラルです、
  • 0x123450x12345678UInt32 リテラルです、
  • 0x1234567890x1234567890adcdefUInt64 リテラルです。

先頭のゼロが値に寄与しない場合でも、それらはリテラルのストレージサイズを決定するためにカウントされます。したがって、0x01UInt8であり、0x0001UInt16です。

ユーザーがサイズを制御できるようにします。

0x で始まる符号なしリテラルは、UInt128 値として表現できないほど大きな整数をエンコードします。そのため、代わりに BigInt 値が構築されます。これは符号なし型ではありませんが、そのような大きな整数値を表現するのに十分な唯一の組み込み型です。

バイナリ、8進数、および16進数のリテラルは、符号なしリテラルの直前に-を付けることで符号を持つことができます。これにより、符号なしリテラルと同じサイズの符号なし整数が生成され、その値の2の補数が得られます。

julia> -0x2
0xfe

julia> -0x0002
0xfffe

プリミティブ数値型(整数など)の最小および最大の表現可能な値は、typemin および typemax 関数によって示されます:

julia> (typemin(Int32), typemax(Int32))
(-2147483648, 2147483647)

julia> for T in [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]

typemintypemax によって返される値は、常に指定された引数の型になります。(上記の式は、for loopsStrings、および Interpolation など、まだ導入されていないいくつかの機能を使用していますが、既存のプログラミング経験を持つユーザーには理解しやすいはずです。)

Overflow behavior

Juliaでは、特定の型の最大表現可能値を超えると、ラップアラウンド動作が発生します:

julia> x = typemax(Int64)
9223372036854775807

julia> x + 1
-9223372036854775808

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

算術演算は、Juliaの整数型で本質的に modular arithmetic を実行し、現代のコンピュータハードウェアにおける整数演算の特性を反映しています。オーバーフローの可能性があるシナリオでは、そのようなオーバーフローから生じるラップアラウンド効果を明示的にチェックすることが重要です。Base.Checked モジュールは、オーバーフローが発生した場合にエラーをトリガーするオーバーフローチェック付きの算術演算のスイートを提供します。どんな状況でもオーバーフローを許容できない使用ケースでは、BigInt 型を利用することが推奨されます。これは Arbitrary Precision Arithmetic で詳述されています。

オーバーフローの動作の例と、それを解決する可能性のある方法は次のとおりです:

julia> 10^19
-8446744073709551616

julia> big(10)^19
10000000000000000000

Division errors

整数除算(div関数)には、ゼロで割る場合と、最小の負の数(typemin)を-1で割る場合の2つの特例があります。これらのケースはどちらもDivideErrorをスローします。余りおよび剰余関数(remおよびmod)は、第二引数がゼロのときに4d61726b646f776e2e436f64652822222c20224469766964654572726f722229_40726566をスローします。

Floating-Point Numbers

リテラル浮動小数点数は、標準フォーマットで表現され、必要に応じて E-notation を使用します:

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

上記の結果はすべて Float64 値です。リテラル Float32 値は、e の代わりに f を書くことで入力できます:

julia> x = 0.5f0
0.5f0

julia> typeof(x)
Float32

julia> 2.5f-4
0.00025f0

値は簡単に Float32 に変換できます:

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

julia> typeof(x)
Float32

16進浮動小数点リテラルも有効ですが、Float64 値としてのみ有効で、p が2進数の指数の前に置かれます:

julia> 0x1p0
1.0

julia> 0x1.8p3
12.0

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

julia> typeof(x)
Float64

半精度浮動小数点数もサポートされています(Float16)、ただし、ソフトウェアで実装されており、計算にはFloat32が使用されます。

julia> sizeof(Float16(4.))
2

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

アンダースコア _ は数字の区切りとして使用できます:

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

Floating-point zero

浮動小数点数には two zeros があり、正のゼロと負のゼロがあります。これらは互いに等しいですが、異なるバイナリ表現を持っています。これは bitstring 関数を使用することで確認できます。

julia> 0.0 == -0.0
true

julia> bitstring(0.0)
"0000000000000000000000000000000000000000000000000000000000000000"

julia> bitstring(-0.0)
"1000000000000000000000000000000000000000000000000000000000000000"

Special floating-point values

実数直線上のどの点にも対応しない3つの指定された標準浮動小数点値があります:

Float16Float32Float64NameDescription
Inf16Inf32Infpositive infinitya value greater than all finite floating-point values
-Inf16-Inf32-Infnegative infinitya value less than all finite floating-point values
NaN16NaN32NaNnot a numbera value not == to any floating-point value (including itself)

さらなる議論については、これらの非有限浮動小数点値が互いにおよび他の浮動小数点数に対してどのように順序付けられているかを参照してください Numeric ComparisonsIEEE 754 standard によれば、これらの浮動小数点値は特定の算術演算の結果です:

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

typemin および typemax 関数は、浮動小数点型にも適用されます:

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

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

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

Machine epsilon

ほとんどの実数は浮動小数点数で正確に表現することができないため、多くの目的において、隣接する表現可能な浮動小数点数の間の距離を知ることが重要です。これはしばしば machine epsilon として知られています。

ジュリアは eps を提供し、1.0 と次に大きい表現可能な浮動小数点値との距離を示します:

julia> eps(Float32)
1.1920929f-7

julia> eps(Float64)
2.220446049250313e-16

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

これらの値は 2.0^-232.0^-52 であり、それぞれ Float32Float64 です。 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ビットの浮動小数点値です。

ジュリアはまた、nextfloatprevfloat 関数を提供しており、これらはそれぞれ引数に対して次に大きいまたは小さい表現可能な浮動小数点数を返します:

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"

この例は、隣接する表現可能な浮動小数点数が隣接するバイナリ整数表現も持つという一般的な原則を強調しています。

Rounding modes

数値が正確な浮動小数点表現を持たない場合、適切な表現可能な値に丸める必要があります。ただし、この丸め方は、IEEE 754 standardに示される丸めモードに従って必要に応じて変更できます。

デフォルトモードは常に RoundNearest が使用され、最も近い表現可能な値に丸められ、結びつきがある場合は最も近い偶数の最下位ビットを持つ値に丸められます。

Background and References

浮動小数点演算には、多くの微妙な点があり、低レベルの実装の詳細に不慣れなユーザーには驚くべきことがあります。しかし、これらの微妙な点は、ほとんどの科学計算に関する書籍や、以下の参考文献で詳細に説明されています:

  • 浮動小数点算術の決定版ガイドは IEEE 754-2008 Standard ですが、オンラインで無料では入手できません。
  • 浮動小数点数がどのように表現されるかについての簡潔で明瞭なプレゼンテーションについては、John D. Cookの article を参照してください。また、彼の introduction も、浮動小数点数の表現が実数の理想化された抽象からどのように異なるかに起因するいくつかの問題について説明しています。
  • また、ブルース・ドーソンの series of blog posts on floating-point numbers も推奨されます。
  • 浮動小数点数とそれらを用いた計算時に遭遇する数値精度の問題についての優れた詳細な議論については、デビッド・ゴールドバーグの論文 What Every Computer Scientist Should Know About Floating-Point Arithmetic を参照してください。
  • さらに浮動小数点数の歴史、理由、問題に関する詳細な文書や、数値計算に関する多くの他のトピックについては、collected writingsを参照してください。これはWilliam Kahanとして一般的に知られており、「浮動小数点の父」と呼ばれています。特に興味深いのは、An Interview with the Old Man of Floating-Pointです。

Arbitrary Precision Arithmetic

任意精度の整数および浮動小数点数での計算を可能にするために、Juliaはそれぞれ GNU Multiple Precision Arithmetic Library (GMP)GNU MPFR Library をラップしています。任意精度の整数および浮動小数点数用の BigIntBigFloat タイプがJuliaで利用可能です。

コンストラクタは、これらの型をプリミティブな数値型から作成するために存在します。そして、string literal @big_str または parse は、AbstractString からそれらを構築するために使用できます。BigInt は、他の組み込み整数型では大きすぎる場合に整数リテラルとしても入力できます。Base には符号なしの任意精度整数型がないため(BigInt はほとんどの場合に十分です)、16進数、8進数、2進数のリテラルを使用できます(10進数リテラルに加えて)。

一度作成されると、Juliaの type promotion and conversion mechanism によって、他のすべての数値型との算術演算に参加します:

julia> BigInt(typemax(Int64)) + 1
9223372036854775808

julia> big"123456789012345678901234567890" + 1
123456789012345678901234567891

julia> parse(BigInt, "123456789012345678901234567890") + 1
123456789012345678901234567891

julia> string(big"2"^200, base=16)
"100000000000000000000000000000000000000000000000000"

julia> 0x100000000000000000000000000000000-1 == typemax(UInt128)
true

julia> 0x000000000000000000000000000000000
0

julia> typeof(ans)
BigInt

julia> big"1.23456789012345678901"
1.234567890123456789010000000000000000000000000000000000000000000000000000000004

julia> parse(BigFloat, "1.23456789012345678901")
1.234567890123456789010000000000000000000000000000000000000000000000000000000004

julia> BigFloat(2.0^66) / 3
2.459565876494606882133333333333333333333333333333333333333333333333333333333344e+19

julia> factorial(BigInt(40))
815915283247897734345611269596115894272000000000

However, type promotion between the primitive types above and BigInt/BigFloat is not automatic and must be explicitly stated.

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

デフォルトの精度(有効数字のビット数)とBigFloat操作の丸めモードは、setprecisionおよびsetroundingを呼び出すことでグローバルに変更できます。これにより、すべての今後の計算はこれらの変更を考慮します。 あるいは、特定のコードブロックの実行中のみ精度や丸めを変更することも可能で、その場合は同じ関数をdoブロックと共に使用します。

julia> setrounding(BigFloat, RoundUp) do
           BigFloat(1) + parse(BigFloat, "0.1")
       end
1.100000000000000000000000000000000000000000000000000000000000000000000000000003

julia> setrounding(BigFloat, RoundDown) do
           BigFloat(1) + parse(BigFloat, "0.1")
       end
1.099999999999999999999999999999999999999999999999999999999999999999999999999986

julia> setprecision(40) do
           BigFloat(1) + parse(BigFloat, "0.1")
       end
1.1000000000004
Warning

setprecision または setrounding@big_str の関係は、big 文字列リテラル(例えば big"0.3")に使用されるマクロであるため、直感的ではないかもしれません。詳細については、4d61726b646f776e2e436f64652822222c2022406269675f7374722229_40726566 のドキュメントを参照してください。

Numeric Literal Coefficients

一般的な数式や表現を明確にするために、Juliaでは変数の前に数値リテラルを直接置くことができ、乗算を暗示します。これにより、多項式の表現がよりクリーンになります:

julia> x = 3
3

julia> 2x^2 - 3x + 1
10

julia> 1.5x^2 - .5x + 1
13.0

指数関数を書くことがよりエレガントになります:

julia> 2^2x
64

数値リテラル係数の優先順位は、否定などの単項演算子の優先順位よりもわずかに低いです。したがって、-2x(-2) * xとして解析され、√2x(√2) * xとして解析されます。しかし、数値リテラル係数は、累乗と組み合わせると単項演算子と似たように解析されます。例えば、2^3x2^(3x)として解析され、2x^32*(x^3)として解析されます。

数値リテラルは、括弧付きの式の係数としても機能します:

julia> 2(x-1)^2 - 3(x-1) + 1
3
Note

数値リテラル係数の暗黙の乗算に使用される優先順位は、乗算(*)や除算(/\、および //)などの他の二項演算子よりも高いです。 これは、例えば 1 / 2im-0.5im に等しく、6 // 2(2 + 1)1 // 1 に等しいことを意味します。

さらに、括弧付きの式は変数の係数として使用でき、式を変数で乗算することを意味します:

julia> (x-1)x
6

二つの括弧付き表現の並置や、括弧付き表現の前に変数を置くことは、乗算を暗示するためには使用できません:

julia> (x-1)(x+1)
ERROR: MethodError: objects of type Int64 are not callable

julia> x(x+1)
ERROR: MethodError: objects of type Int64 are not callable

両方の式は関数適用として解釈されます:数値リテラルでない任意の式が、すぐに括弧で続く場合、それは括弧内の値に適用される関数として解釈されます(関数についての詳細は Functions を参照してください)。したがって、これらのケースの両方で、左側の値が関数でないためエラーが発生します。

上記の構文強化は、一般的な数学的公式を書く際に発生する視覚的ノイズを大幅に減少させます。数値リテラルの係数と、それが掛け算する識別子または括弧付きの表現の間に空白を入れてはいけないことに注意してください。

Syntax Conflicts

対比されたリテラル係数構文は、いくつかの数値リテラル構文と衝突する可能性があります:16進数、8進数および2進数の整数リテラル、浮動小数点リテラルの工学表記法です。以下は、構文の衝突が発生するいくつかの状況です:

  • 16進数整数リテラル式 0xff は、数値リテラル 0 が変数 xff に掛けられていると解釈される可能性があります。同様の曖昧さは、8進数や2進数リテラル 0o7770b01001010 にも見られます。
  • 浮動小数点リテラル表現 1e10 は、数値リテラル 1 が変数 e10 で掛けられていると解釈される可能性があります。同様に、同等の E 形式でも同じです。
  • 32ビット浮動小数点リテラル式 1.5f22 は、数値リテラル 1.5 が変数 f22 と掛け合わされると解釈される可能性があります。

すべての場合において、曖昧さは数値リテラルとしての解釈に有利に解決されます:

  • 0x/0o/0bで始まる表現は常に16進数/8進数/2進数リテラルです。
  • 数値リテラルで始まり、その後に e または E が続く式は常に浮動小数点リテラルです。
  • 数値リテラルで始まり、その後に f が続く式は常に32ビット浮動小数点リテラルです。

Eが歴史的な理由から数値リテラルにおいてeと同等であるのに対し、Fは単なる別の文字であり、数値リテラルにおいてfのようには振る舞いません。したがって、数値リテラルの後にFが続く式は、数値リテラルが変数で乗算されるものとして解釈されます。つまり、例えば1.5F221.5 * F22と等しいです。

Literal zero and one

Juliaは、指定された型または与えられた変数の型に対応するリテラル0および1を返す関数を提供します。

FunctionDescription
zero(x)Literal zero of type x or type of variable x
one(x)Literal one of type x or type of variable x

これらの関数は、不要な type conversion からのオーバーヘッドを回避するために Numeric Comparisons で役立ちます。

例:

julia> zero(Float32)
0.0f0

julia> zero(1.0)
0.0

julia> one(Int32)
1

julia> one(BigFloat)
1.0