実数型は、単純型の1つで順序型には含まれません。ここでは実数型について説明します。
32bitプラットフォームと64bitプラットフォームで違いがあるので注意してください。
実数型 |
|---|
実数型は、数学でいう実数の部分集合を表します。
Object Pascal では、IEEE-754 浮動小数点を使用します。IEEE-754 浮動小数点には4バイト浮動小数点(単精度)と8バイト浮動小数点(倍精度)があります。
32bitプラットフォームでは、10バイト浮動小数点(拡張精度)が使用可能です。64bitプラットフォームでは10バイト浮動小数点(拡張精度)は使用できません。
実数型は、順序型と違い、先行値(1つ前の値)と後続値(1つ後の値)という概念はありません。
■実数型の範囲とサイズ 値には正・負があり、範囲は絶対値を示しています。
| 型 | 値の範囲 (最小 .. 最大) | サイズ | 有効桁数(10進数) | |
|---|---|---|---|---|
| Real | 5.0E-324 .. 1.7E308 | 8 バイト (64bit) | 15桁 *1) | |
| Single | 1.5E-45 .. 3.4E38 | 4 バイト (32bit) | 7桁 | |
| Double | 5.0E-324 .. 1.7E308 | 8 バイト (64bit) | 15桁 | |
| Extended | 1.9E-4932 .. 1.1E4932 | 10 バイト (80bit) | 19桁 | |
| 5.0E-324 .. 1.7E308 | 8 バイト (64bit) | 15桁 *2) |
*1) Real 型は、プラットフォーム依存のネイティブ実数ですが、ここでは Double と同じになります。
*2) 64bitプラットフォームでは、10バイト浮動小数点(拡張精度)が使用できないため、Extended 型は Double 型と同じになります。
Object Pascal には、上記の実数の他に、特殊な実数の Comp 型と Currency 型があります。
これらは、実数に分類されていますが、内部的には8バイト整数として使用されます。
■特殊な実数型の範囲とサイズ
| 型 | 値の範囲 (最小 .. 最大) | サイズ | |
|---|---|---|---|
| Comp | -9223372036854775808 .. 9223372036854775807 | 8 バイト | |
| Currency | -922337203685477.5808 .. 922337203685477.5807 | 8 バイト |
Currency 型は、内部的には Comp の様に整数で持っていて、計算するときに自動的に 10,000で除算したり乗算して桁を調整します。
内部的には整数ですが、実数扱いなので、先行値(1つ前の値)と後続値(1つ後の値)という概念はありません。
64bitプラットフォームでは、実数の定数で指定できる桁数は 15桁程度なので、それ以上の桁数の Comp 型や Currency 型をリテラル定数で指定することはできません。
32bitプラットフォームから64bitプラットフォームに移行する場合は注意が必要です。
実数型の内部表現 |
|---|
■Single型のフォーマット(IEEE-754 単精度実数)
1bitの符号(S)、8bitの指数部、23bitの仮数部があります。データはすべて2進数です。
± 1.m × (2のe乗) に正規化された値となります。値が 0 の場合は全bitが 0 になります。
符号は、0が正、1が負を表します。
指数部は、仮数部の小数点位置を指定するための指数eを表します。10進数で127でバイアスされた値です。
仮数部は2進数で 1.m (m:23桁の2進数)で表され、mの23bitが仮数部を表します。整数部の 1 は省略されます(ケチ表現)。
省略された1桁を含めると数値の精度は2進数で24bitになります。
10進数にすると0〜16777215になり、0〜9999999を表すことができるため、10進数の有効桁数は7桁となります。
■Double型のフォーマット(IEEE-754 倍精度実数)
1bitの符号(S)、11bitの指数部、52bitの仮数部があります。データはすべて2進数です。
± 1.m × (2のe乗) に正規化された値となります。値が 0 の場合は全bitが 0 になります。
符号は、0が正、1が負を表します。
指数部は、仮数部の小数点位置を指定するための指数eを表します。10進数で1023でバイアスされた値です。
仮数部は2進数で 1.m (m:52桁の2進数)で表され、mの52bitが仮数部を表します。整数部の 1 は省略されます(ケチ表現)。
省略された1桁を含めると数値の精度は2進数で53bitになります。
10進数にすると0〜9007199254740991になり、0〜999999999999999を表すことができるため、10進数の有効桁数は15桁となります。
■Extended型のフォーマット(IEEE-754準拠 拡張精度実数)
IEEE-754では、拡張精度の浮動小数点を明確には定義していません。10バイト浮動小数点は拡張精度の条件を満たしているので準拠していることになります。
64bitプラットフォームでは、10バイト浮動小数点(拡張精度)は使用できません。
1bitの符号(S)、15bitの指数部、64bitの仮数部があります。データはすべて2進数です。
± 1.m × (2のe乗) に正規化された値となります。値が 0 の場合は全bitが 0 になります。
符号は、0が正、1が負を表します。
指数部は、仮数部の小数点位置を指定するための指数eを表します。10進数で16383でバイアスされた値です。
仮数部は2進数で 1.m (m:63桁の2進数)で表され、整数部の 1 とmの64bitが仮数部を表します。整数部の 1 は省略されません。
数値の精度は2進数で64bitになります。
10進数にすると0〜18446744073709551615になり、0〜9999999999999999999を表すことができるため、10進数の有効桁数は19桁となります。
実数リテラルの型 |
|---|
Free Pascalでは、最小の精度で表現できる型を選択します。
つまり、10進数の実数リテラルを2進浮動小数点に変換したときに、仮数部が24bit以内で表せるときはSingle型になります。仮数部が24bitを超える場合はDouble型またはExtended型になります。
10進数では近い数値でも2進数にすると必要な桁数がまったく違うので注意が必要です。
■実数リテラルと型選択の例(64bitプラットフォーム)
| 10進数の実数リテラル | 型の選択 | 2進数の実数値 | |
|---|---|---|---|
| 123.0 | Single | 1111011.0 | |
| 123456789.0 | Double | 111010110111100110100010101.0 | |
| 0.1 | Souble | 0.00011001100110011001100110011... | |
| 0.5 | Single | 0.1 | |
| 3.14 | Double | 11.0010001111010111000010100011... | |
| 7.723876953125 | Single | 111.101110010101 |
型キャストで型を指定 |
|---|
実数リテラルをDobleとして扱いたい場合は、明示的な型のキャストを行います。
■キャストの書式
型名(変数またはリテラル)
■キャストの例(Double型へキャスト)
Double(0.5) // Single型の実数リテラルをDouble型にキャストします。
Double(3.14) // Double型の実数リテラルをDouble型にキャストします。Double型をDouble型にキャストしても問題ありません。
Double(123) // 整数を実数のDouble型にキャストすることもできます。123を実数として扱うと暗黙の型変換でSingle型になります。
Double('ABC') // 文字列型を実数のDouble型への変換はできないため、コンパイル時にエラーとなります。
ここでは実数について説明しましたが、キャストは他の型でも使用できます。変換不可能な型変換の場合はコンパイル時にエラーとなります。
コンパイラディレクティブで型選択モードの変更 |
|---|
型キャストでは、指定したものだけが対象となりますが、自動的に実数リテラルをDouble型にしたいときは「$MINFPCONSTPREC 64」ディレクティブを指定します。
値は、実数の型の選択で最小の型のbit数を指定します。
{$MINFPCONSTPREC 64}は、すべてDouble型になります。
{$MINFPCONSTPREC 32}または{$MINFPCONSTPREC DEFAULT}は、既定の動作で、実数の値によりSingleかDoubleで格納可能な最小の型を選択します。
値に80を指定することはできません。
このディレクティブはローカルディレクティブのため、同一ソースファイル内に限定され、指定した場所以降に有効となります。他のソースコードには影響ありません。
同一ソースファイル内の場所ごとに違う指定をすることが可能です。
アプリ全体で指定したい場合は、programや各unitの実行文部より前に指定します。
コンパイラのコマンドライン引数で型選択モードの変更 |
|---|
コンパイラ(fpc.exe)のコマンドラインオプションに「-CF値」を指定します。
値は、実数の型の選択で最小の型のbit数を指定します。
-CF64 は、すべてDouble以上にする。
-CF32 は、既定の動作で、実数の値によりSingleかDoubleを選択する。
値に80を指定することはできません。
コマンドラインオプションはコンパ対対象のソースコード全体に効果がありますが、ソースコードの中に「$MINFPCONSTPREC 値」ディレクティブがある場合は、コマンドラインオプションよりディレクティブが優先されます。
実数の演算 |
|---|
実数の四則演算などの計算では、演算項の大きい方の型に合わせて格上げされて計算し、結果の型も大きい方の型になります。
例えば、Single型 * Double型 は、Double型に格上げされて結果もDouble型になりますが、Single型 * Single型 は、Single型で計算され、結果もSingle型になります。この場合、計算により桁数が増えることになってもSingle型に丸められてしまいます。
Single型の値をDouble型の変数に代入してもDouble型にしても精度が上がることはありません。
■$MINFPCONSTPRECディレクティブやDouble型キャストを指定した計算例
program Sample1;
{$MODE OBJFPC}{$H+}
{$CODEPAGE UTF8}
uses
SysUtils;
var
X : Double; // XはDouble型の変数
begin
X := 1.0 / 3.0;
WriteLn(X:0:15); //@ 0.333333343267441 (Single型の精度)
{$MINFPCONSTPREC 64}
X := 1.0 / 3.0;
WriteLn(X:0:15); //A 0.333333333333333 (Double型の精度)
{$MINFPCONSTPREC 32}
X := 1.0 / 3.0;
WriteLn(X:0:15); //B 0.333333343267441 (Single型の精度)
X := Double(1.0) / Double(3.0);
WriteLn(X:0:15); //C 0.333333333333333 (Double型の精度)
end
上記ソースコードを、コマンドラインオプション -CF64 を指定してコンパイルして実行すると、@もDouble型となりAと同じになります。コマンドラインオプションよりコンパイラディレクティブが優先されるため、BはSingle型になります。
CのようにDouble型へのキャストを指定した場合は、型の選択モードに関係なくDouble型で計算されるためDouble型の精度の計算結果となります。
常に64bit実数選択にしたい場合は、上記の設定の他に Free Pascalの設定ファイル(fpc.cfg) に「-CF64」を追加する方法もあります。この場合もソースコード中のコンパイラディレクティブが優先されます。
計算重視のアプリを作成する場合は以下の対応を検討してください。
以下を単独または組み合わせて対応してください。
A. Doubleの型キャストを使用する。
B. コンパイラディレクティブ「$MINFPCONSTPREC 64」を使用する。
C. コンパイラのコマンドラインオプション「-CF64」を使用する。
D. Free Pascalの設定ファイル fpc.cfg に「-CF64」を設定する。
※ A.B.はソースファイルの対応。C.はコンパイル操作時の対応。D.はFree Pascalの設定環境。