拡張精度とは、基本浮動小数点形式よりも高い精度を提供する浮動小数点数形式を指します。 [ 1 ]拡張精度形式は、基本形式の式の中間値における丸め誤差とオーバーフロー誤差を最小限に抑えることで、基本形式をサポートします。拡張精度とは対照的に、任意精度演算とは、特別なソフトウェア(またはまれにハードウェア)を使用して、はるかに大きな数値型(通常は2のべき乗ではない記憶領域を持つ)を実装することを指します。
拡張浮動小数点形式の歴史は長く、20世紀半ばにまで遡ります。さまざまなメーカーが、異なるマシン向けに異なる形式の拡張精度を使用してきました。多くの場合、拡張精度の形式は、拡張対象である通常の単精度および倍精度形式のスケールアップとは全く同じではありません。ごくまれに、実装は単に浮動小数点データ形式のソフトウェアベースの変更でしたが、ほとんどの場合、拡張精度はハードウェアで実装され、中央処理装置自体に組み込まれるか、より一般的には、「浮動小数点ユニット」(FPU)または「浮動小数点プロセッサ」(FPP )と呼ばれるオプションの接続プロセッサのハードウェアに組み込まれ、高速入出力デバイスとしてCPUからアクセス可能でした。
1965 年に販売されたIBM 1130 [ 2 ]は、32 ビットの「標準精度」形式と 40 ビットの「拡張精度」形式の 2 つの浮動小数点形式を提供しました。標準精度形式は 24 ビットの 2 の補数仮数部を含み、拡張精度は 32 ビットの 2 の補数仮数部を使用します。後者の形式は、CPU の 32 ビット整数演算をフル活用します。両方の形式の特徴は、128でバイアスされた2 のべき乗を含む 8 ビットのフィールドです。浮動小数点演算はソフトウェアによって実行され、倍精度は全くサポートされていません。拡張形式は 3 つの 16 ビットワードを占有し、余分なスペースは単純に無視されます。[ 3 ]
IBM System/360 は、 32 ビットの「ショート」浮動小数点形式と 64 ビットの「ロング」浮動小数点形式をサポートしています。[ 4 ] 360/85 および後継のSystem/370では、128 ビットの「拡張」形式のサポートが追加されました。[ 5 ]これらの形式は現在の設計でも引き続きサポートされており、現在は「16 進浮動小数点」(HFP) 形式と呼ばれています。
6502 CPU用の Microsoft BASIC ポートは、Commodore BASIC、AppleSoft BASIC、KIM-1 BASIC、MicroTAN BASICなどの適応版において、1977 年以来、浮動小数点フォーマットの拡張 40 ビット版であるMicrosoft Binary Format (MBF)をサポートしています。 [ 6 ]
IEEE 754浮動小数点規格では、実装において拡張精度フォーマットを提供することを推奨しています。この規格では拡張フォーマットの最小要件を規定していますが、エンコーディングは規定していません。[ 7 ]エンコーディングは実装者の選択です。[ 8 ]
IA32 、x86-64、およびItaniumプロセッサは、この標準規格において最も影響力のあるフォーマットである、次のセクションで説明するIntel 80ビット(64ビット仮数)「ダブル拡張」フォーマットをサポートしています。
Motorola 6888x数学コプロセッサとMotorola 68040および68060プロセッサも 64 ビットの仮数部拡張精度フォーマットをサポートしています (Intel フォーマットに似ていますが、 指数部と仮数部の間に 16 ビットの未使用ビットが挿入されて 96 ビットフォーマットにパディングされ、指数部がゼロでビット 63 が 1 の値は正規化された値になります[ 9 ] )。後継のColdfireプロセッサはこの 96 ビット拡張精度フォーマットをサポートしていません。[ 10 ]
初期のARMプロセッサ用のFPA10数学コプロセッサも、64ビットの仮数部拡張精度フォーマット(Intelフォーマットに似ているが、 符号フィールドと指数フィールドの間に16ビットのゼロを挿入して96ビットフォーマットにパディングされている)をサポートしているが、正しい丸め処理は行っていない。[ 11 ]
x87およびMotorola 68881の80ビットフォーマットは、IEEE 754-1985ダブル拡張フォーマットの要件を満たしており[ 12 ] 、 IEEE 754 128ビットバイナリフォーマットも同様です。
x86拡張精度フォーマットは、 Intel 8087数学コプロセッサで初めて実装された80ビットフォーマットであり、浮動小数点演算ユニット(FPU)を搭載したx86設計に基づくすべてのプロセッサでサポートされています。
Intel 8087 は、ハードウェアで浮動小数点演算をサポートする最初のx86デバイスでした。浮動小数点数をエンコードおよび交換するために、32 ビットの「単精度」形式と 64 ビットの「倍精度」形式をサポートするように設計されました。拡張形式は、データをより高い精度で格納するためではなく、中間計算でのオーバーフローと丸め誤差を最小限に抑えることで、一時的な倍精度の結果を、より信頼性が高く正確に計算できるようにするために設計されました。[ a ] [ 14 ] [ 15 ] 8087 のすべての浮動小数点レジスタはこの形式を保持しており、メモリからレジスタをロードするときに数値をこの形式に自動的に変換し、レジスタをメモリに格納するときに結果をより一般的な形式に変換します。中間部分式の結果を拡張精度スクラッチ変数に保存してプログラミング言語のステートメント間で継続し、中断された計算を中断された場所から再開できるようにするため、変換を行わずにこれらの内部レジスタとメモリ間で値を転送する命令が提供され、それによって計算の拡張フォーマットへのアクセスが可能になります[ b ] – また、そのような数値の関数の精度の問題が、より高い精度で再び浮上します。
以降のすべてのx86プロセッサの浮動小数点ユニット( FPU) は、このフォーマットをサポートしています。その結果、このフォーマットによって提供されるより高い精度を活用するソフトウェアを開発できます。x87演算と最初の IEEE 754 標準提案の主要設計者であるWilliam Kahan は、 x87浮動小数点の開発について次のように述べています。「我々が敢えてした限り広い (80 ビット) 拡張フォーマットは、Hewlett-Packard の 10 進数電卓で13 進数の内部フォーマットが果たすのと同じサポートの役割を果たすために含まれました。」[ 17 ] さらに Kahan は、8087 ではサイクル時間を増やすことなくキャリー伝播を実行できる最大の仮数ビットは 64 ビットであったこと、[ 18 ]また、x87 拡張精度は将来のプロセッサでより高い精度に拡張できるように設計されたことを指摘しています。
この 80 ビット形式は、仮数の符号に 1 ビット、 指数フィールドに 15 ビット (つまり 128 ビットの4 倍精度 IEEE 754 形式 と同じ範囲)、仮数に64ビットを使用します。指数フィールドは 16383 でバイアスされているため、 2の実際のべき乗を計算するには、指数フィールドの値から 16383 を減算する必要があります。[ 20 ]指数フィールドの値 32767 (15 ビットすべてが1 ) は、無限大や非数などの特殊な状態を表現できるように予約されています。指数フィールドがゼロの場合、値は非正規数であり、2 の指数は -16382 です。[ 21 ]
![]()
次の表において、「s」は符号ビットの値(0は正、1は負)、「e」は指数フィールドの値(正の整数として解釈される)、「m」は仮数部(正の2進数として解釈される)であり、2進小数点はビット 63と62の間に位置します。「m」フィールドは、上記の図の整数部と小数部の組み合わせです。
単精度および倍精度フォーマットとは対照的に、このフォーマットでは暗黙の/隠しビットは使用されません。代わりに、ビット 63には仮数の整数部分が、ビット 62~0には小数部分が保持されます。正規化されたすべての数値において、ビット63は1になります。8087の開発当時 、この設計にはいくつかの利点がありました。
これらの例は、浮動小数点値をビット表現(16進数)で示したものです。これには、符号、(バイアス付き)指数部、および仮数部が含まれます。
0000 0000 0000 0000 0001 16 = 2 −16382 × 2 −63 = 2 −16445 ≈ 3.64519953188247460252841 × 10 −4951 (最小の正の非正規数)
0000 7fff ffff ffff ffff 16 = 2 −16382 × (1 − 2 −63 ) ≈ 3.36210314311209350589816 × 10 −4932 (最大の異常数)
0001 8000 0000 0000 0000 16 = 2 −16382 ≈ 3.36210314311209350626268 × 10 −4932 (最小の正の正規数)
7ffe ffff ffff ffff ffff 16 = 2 16384 × (1 − 2 −64 ) ≈ 1.18973149535723176502126 × 10 4932 (最大の通常の数)
3ffe ffff ffff ffff ffff 16 = 1 − 2 −64 ≈ 0.99999999999999999994579 (1未満の最大の数)
3fff 8000 0000 0000 0000 16 = 1 (1)
3fff 8000 0000 0000 0001 16 = 1 + 2 −63 ≈ 1.00000000000000000010842 (1より大きい最小の数)
4000 8000 0000 0000 0000 16 = 2 c000 8000 0000 0000 0000 16 = −2
0000 0000 0000 0000 0000 16 = 0 8000 0000 0000 0000 0000 16 = −0
3ffd ああああああああああああああ16 ≈ 0.33333333333333333334237 (⅓に最も近い近似値)4000 adf8 5458 a2bb 4a9b 16 ≈ 2.71828182845904523542817 (eに最も近い近似値)
4000 c90f daa2 2168 c235 16 ≈ 3.14159265358979323851281 (πに最も近い近似値)
80 ビット浮動小数点形式は、当初は一般的な 32 ビットおよび 64 ビット浮動小数点サイズのみを提供していた C、Fortran および同様のコンピュータ言語の開発後、1984 年までに広く利用可能になりました[ 25 ]。x86 設計では、現在ほとんどのCコンパイラがlong double型を介して 80 ビット拡張精度をサポートしており、これはC99 / C11規格 (IEC 60559 浮動小数点演算 (付録 F)) で規定されています。他の言語用の x86 上のコンパイラも、非標準の拡張機能を介して拡張精度をサポートすることがよくあります。たとえば、Turbo Pascal は型を提供しextended、いくつかのFortranコンパイラはREAL*10型 (およびに類似REAL*4)を持っています。このようなコンパイラは通常、平方根や三角関数などのREAL*8拡張精度数学サブルーチンを標準ライブラリに含めています。
80ビット浮動小数点形式の範囲(サブノーマルを含む)は約3.65 × 10⁻⁴⁹⁵¹から1.18 × 10⁻⁴⁹⁵¹までです。+4932。log 10 ( 2 64 ) ≈ 19.266ですが、この形式は通常、約 18 桁の有効精度(保証される最小精度であるlog 10 ( 2 63 )のフロア) を与えるものとして説明されます。バイナリについて話すときに 10 を使用することは残念です。なぜなら、ほとんどの 10 分の 1 は、10 の 2/3と同様に、バイナリでは循環シーケンスだからです。したがって、10.15 のような値は、バイナリでは 10 の 10.1499996185 などと同等です バイナリではREAL*410.15000000000000035527 などREAL*8となります。相互変換には近似が含まれますが、0.625 のように正確なバイナリ値を表す少数の 10 分の 1 は例外です 。の場合REAL*10、10 進数文字列は 10.14999999999999999996530553 などとなります。最後の 9 桁は 18 番目の小数部であり、したがって文字列の 20 番目の有効桁です。 80 ビット形式の 10 進数と 2 進数間の変換の境界は、次のように与えられます。 最大 18 有効桁を持つ 10 進数文字列が (入力時と同様に) 80 ビット IEEE 754 2 進浮動小数点値に正しく丸められ、 その後 (出力時と同様に) 同じ数の 10 進数の有効桁に変換し直した場合、最終的な文字列は元の文字列と完全に一致します。 一方、逆に、80 ビット IEEE 754 2 進浮動小数点値が正しく変換され、 (最も近い) 丸められて、少なくとも 21 桁の有効桁を持つ 10 進数文字列になり、 その後 2 進数形式に変換し直した場合、元の文字列と完全に一致します。 [ 12 ]これらの近似は、任意精度演算によって計算されるような、数式中の定数の最適な値を高精度で指定する場合に特に厄介です。
拡張精度形式の仮数部に最低 64 ビットの精度が必要であること を示す顕著な例として、倍精度値に対してべき乗演算を行う際に精度損失を回避する必要性が挙げられます。[ 26 ] [ 27 ] [ 28 ] [ c ] x86浮動小数点演算ユニットは、べき乗演算を直接実行する命令を提供していません。代わりに、プログラムが次の式を使用してべき乗演算を順次実行できる一連の命令を提供しています。
精度損失を避けるため、中間結果「log 2 ( x )」と「y ·log 2 ( x ) 」は、より高い精度で計算する必要があります。これは、 xの指数部と仮数部の両方が、中間結果の仮数部に収まる必要があるためです。その後、2つの中間結果が計算される際に、中間結果の仮数部は最終結果の指数部と仮数部に分割されます。以下の説明では、この要件についてさらに詳しく説明します。
少し分解してみると、IEEE 754倍精度浮動小数点値は次のように表すことができます。
ここで、sは指数の符号 (0 または 1)、Eは不偏指数 (0 から 1023 までの整数)、Mは仮数(1 ≤ M < 2の範囲の 53 ビット値) です。負の数とゼロは、これらの値の対数が定義されていないため無視できます。この議論の目的上、M は1 以上に制限されているため、 53 ビットの精度を持ちません。つまり、隠しビットは精度にカウントされません ( Mが 1 未満の場合、値は実際には非正規化され、すでに精度が失われている可能性があります。この状況はこの記事の範囲外です)。
倍精度浮動小数点数のこの表現の対数を取って簡略化すると、次のようになります。
この結果は、 ある数の底が2の対数を取る場合、元の値の指数の符号が対数の符号になり、元の値の指数が対数の仮数の整数部分になり、元の値の仮数が対数の仮数の小数部分に変換されることを示しています。
Eは 0 から 1023 の範囲の整数であるため、 対数の整数部分を表すには、小数点の左側に最大 10 ビットが必要です。Mは1 ≤ M < 2の範囲にあるため、log 2 Mの値は0 ≤ log 2 M < 1の範囲にあり、対数の小数部分を表すには、小数点の右側に少なくとも 52ビットが必要です。小数点の左側の 10 ビットと小数点の右側の 52 ビットを組み合わせると、対数の仮数部は少なくとも 62 ビットの精度で計算する必要があります。実際には、 Mの値が1023 未満の場合、 小数点の右側に53 ビットが必要で、 Mの値は以下 精度損失を避けるため、小数点以下に54ビットのビット数が必要となります。小数点以下の精度を高めるというこの要件とのバランスを取るため、512未満の 指数では小数点以下に9ビット、256未満の指数では 小数点以下に8ビットのビット数が必要となります。
べき乗計算の最終段階は、中間結果を計算することです。「中間結果」は、整数部分「I」と小数部分「F 」を足し合わせたものです。中間結果が負の場合は、「 I」と「F 」の両方が負の数であるため、小数部分が正になるように若干の調整が必要です。
良好な中間結果を得るために:
中間結果が陰性の場合:
したがって、中間結果の整数部分(「I」または「I − 1」)にバイアスを加えたものが最終結果の指数となり、中間結果の変換された正の小数部分(2Fまたは2F + 1)が最終結果の仮数となります。最終結果に52ビットの精度を持たせるためには、正の小数部分を少なくとも52ビットに維持する必要があります。
結論として、中間結果の仮数部に必要な精度ビット数はデータによって多少異なりますが、倍精度 数を扱うほとんどのべき乗計算では、64ビットあれば精度損失を回避するのに十分です。
拡張精度形式の指数に必要なビット数は、拡張形式を使用して計算した2つの倍精度数の積がオーバーフローしないという要件から導き出されます。倍精度値の指数の最大値は1023なので、2つの倍精度数の積の最大値の指数は2047(11ビット値)になります。負の指数を考慮するためのバイアスを加えると、指数フィールドは少なくとも12 ビット幅でなければなりません。
これらの要件、 すなわち符号に 1 ビット、 バイアス付き指数に 12 ビット、 仮数に 64 ビットを組み合わせると、拡張精度フォーマットには少なくとも 77 ビットが必要になります。エンジニアリング上の考慮事項により、最終的に 80 ビット フォーマットが定義されました (特に IEEE 754 規格では、拡張精度フォーマットの指数範囲が、次に大きい15 ビットの4倍精度フォーマットの範囲と一致することが要求されています )。[ 27 ]
拡張精度演算の恩恵を受ける計算のもう1つの例は、反復改良スキームです。これは、数値線形代数で通常行われる非常に多くの計算中に直接解に蓄積された誤差を間接的に除去するために使用されます。[ 30 ]
long double、x86 システムで 80 ビット浮動小数点数を使用して実装しています。ただし、これは実装依存の動作であり、必須ではありませんが、C99規格「Annex F IEC 60559 浮動小数点演算」 で IEEE 754 ハードウェア向けに規定されているように、標準で許可されています。GCC は、型も提供しています。[ 31 ] __float80__float128long-float、x86システム上で80ビット浮動小数点数を使用して実装しているものがある。real他の マシンでは、CPUがネイティブにサポートする最大の浮動小数点型、または64ビット倍精度のいずれか大きい方が使用されます。extendedに加えて 80 ビット型が利用可能です。これは、ネイティブ (80x87 コプロセッサが存在する場合) またはエミュレート (Turbo87 ライブラリ経由) のいずれかで使用できます。この型は、16 ビット、32 ビット、および 64 ビットのプラットフォームで、場合によってはパディング付きで使用できます。[ 32 ]realsingle double extendedFloat80。EXTますEXTENDED。