拡張精度とは、基本的な浮動小数点形式よりも高い精度を提供する浮動小数点数形式を指します。 [1]拡張精度形式は、基本形式の式の中間値の丸め誤差とオーバーフロー誤差を最小限に抑えることで、基本形式をサポートします。拡張精度とは対照的に、任意精度演算は、特別なソフトウェア(またはまれにハードウェア)を使用して、はるかに大きな数値型(通常は2の累乗ではないストレージカウントを持つ)を実装することを指します。
拡張精度実装
拡張浮動小数点形式の歴史は、ほぼ前世紀の中頃まで遡ります。[いつ? ]。さまざまなメーカーが、さまざまなマシンの拡張精度にさまざまな形式を使用しています。多くの場合、拡張精度の形式は、拡張対象の通常の単精度および倍精度形式のスケールアップとはまったく同じではありません。実装が浮動小数点データ形式のソフトウェアベースの変更だけだったケースもいくつかありますが、ほとんどの場合、拡張精度はハードウェアで実装され、中央プロセッサ自体に組み込まれているか、より一般的には、高速入出力デバイスとして CPUにアクセス可能な「浮動小数点ユニット」(FPU) または「浮動小数点プロセッサ」( FPP )と呼ばれるオプションの接続プロセッサのハードウェアに組み込まれています。
IBM 拡張精度形式
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) 形式と呼ばれています。
Microsoft MBF 拡張精度形式
6502 CPU用のMicrosoft BASICポート( Commodore BASIC、AppleSoft BASIC、KIM-1 BASIC、MicroTAN BASICなどの適応版)は、1977年以来、浮動小数点形式Microsoft Binary Format(MBF)の拡張40ビットバリアントをサポートしています。 [6]
IEEE 754 拡張精度形式
IEEE 754浮動小数点規格では、実装で拡張精度形式を提供することが推奨されています。この規格では拡張形式の最小要件は規定されていますが、エンコードは規定されていません。[7]エンコードは実装者が選択します。[8]
IA32 、x86-64、およびItaniumプロセッサは、この標準でこれまでで最も影響力のある形式である、次のセクションで説明する Intel 80 ビット (64 ビットの仮数部)「倍精度拡張」形式をサポートしています。
モトローラ6888x数値演算コプロセッサとモトローラ 68040および68060プロセッサも、64 ビットの拡張精度仮数形式をサポートしています (Intel 形式に似ていますが、指数と仮数フィールドの間に 16 ビットの未使用ビットが挿入され、指数が 0 でビット 63 が 1 の値は正規化された値になります[9] )。後継のColdfireプロセッサでは、この 96 ビット拡張精度形式はサポートされていません。[10]
初期のARMプロセッサ用のFPA10数値演算コプロセッサも、64ビットの拡張精度形式(符号フィールドと指数フィールドの間に16ビットのゼロが挿入された96ビット形式にパディングされている点ではIntel形式に似ている)をサポートしていますが、正しい丸めは行われません。[11]
x87とモトローラ68881の80ビット形式は、IEEE 754-1985の倍精度拡張形式[12]の要件を満たしており、 IEEE 754の128ビットバイナリ形式も同様です。
x86 拡張精度形式
x86 拡張精度形式は、 Intel 8087数学コプロセッサで最初に実装された 80 ビット形式であり、浮動小数点ユニット(FPU)を組み込んだx86 設計に基づくすべてのプロセッサでサポートされています。
Intel 8087 は、ハードウェアで浮動小数点演算をサポートした最初のx86デバイスでした。これは、浮動小数点数のエンコードと交換のために、32 ビットの「単精度」形式と 64 ビットの「倍精度」形式をサポートするように設計されました。拡張形式は、より高い精度でデータを格納するためではなく、中間計算でのオーバーフローと丸め誤差を最小限に抑えることで、一時的な倍精度の結果をより確実かつ正確に計算できるようにするために設計されました。[a] [14] [15] 8087 のすべての浮動小数点レジスタはこの形式を保持しており、レジスタをメモリからロードするときに数値をこの形式に自動的に変換し、レジスタをメモリに戻すときに結果をより一般的な形式に変換します。中間部分式の結果を拡張精度スクラッチ変数に保存してプログラミング言語ステートメント間で継続できるようにし、中断された計算を中断された場所から再開できるようにするために、これらの内部レジスタとメモリ間で値を変換せずに転送する命令が提供され、これにより計算用の拡張形式にアクセスできるようになります[b]。これにより、このような数値の関数の精度の問題も再燃しますが、精度は高くなります。
後続のすべてのx86プロセッサの浮動小数点ユニット( FPU) は、この形式をサポートしています。その結果、この形式が提供する高精度を活用するソフトウェアを開発できます。x87算術演算の主要設計者であり、初期の IEEE 754 標準提案者であるWilliam Kahan は、x87 浮動小数点の開発について次のように述べています。「ヒューレット パッカードの 10 進計算機で 13 進内部形式が果たすのと同じサポートの役割を果たすために、可能な限り広い拡張形式 (80 ビット) が組み込まれました。」[17] さらに、Kahan は、8087 でサイクル タイムを増やすことなく桁上げの伝播を実行できる最も広い仮数部は 64 ビットであり、[18] x87 拡張精度は将来のプロセッサでより高い精度に拡張できるように設計されていると述べています。
- 「今のところ、10バイトの拡張フォーマットは、超高精度演算の価値と、それを高速に実行するための実装コストとの間の許容できる妥協点です。もうすぐ2バイトの精度が許容できるようになり、最終的には16バイトのフォーマットになります。...浮動小数点演算のIEEE標準754が策定されたときから、より広い精度へのそのような段階的な進化はすでに見込まれていました。」[19]
この 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の開発 中、この設計にはいくつかの利点がありました。
- 仮数部のすべてのビットがレジスタ内に存在する場合、計算は少し速く完了します。
- 64 ビットの仮数部は、ほとんどの場合に結果を倍精度形式に戻すときに精度の低下を回避するのに十分な精度を提供します。
- このフォーマットは、アンダーフローによる精度の低下を示すメカニズムを提供し、これをさらに演算に引き継ぐことができます。たとえば、計算2 × 10 −4930 × 3 × 10 −10 × 4 × 1020 は 中間結果6 × 10 −4940 を生成し、これは非正規化、精度の損失も伴う。すべての項の積は24 × 10 −4920であり、これは正規化された数として表すことができる。80287 はこの計算を完了し、「非正規化」結果 (指数が 0 でない、ビット 63 = 0) を返すことで精度の損失を示すことができた。[22][23]80387 以降のプロセッサは非正規化数を生成しなくなり、演算への非正規化入力をサポートしなくなった。アンダーフローが発生した場合は非正規化数を生成するが、非正規化数に対する後続の演算が正規化できる場合は正規化された結果を生成する。[24]
使用方法の紹介
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 −4951 から1.18 × 10+4932。log 10 ( 2 64 ) ≈ 19.266ですが、この形式は通常、約18桁の精度( log 10 ( 2 63 )の床、つまり最小保証精度)を与えると説明されています。バイナリについて話すときに小数点を使用するのは残念です。なぜなら、ほとんどの小数はバイナリでは繰り返しシーケンスであるためです。2/3は 10 進数です。したがって、10.15 などの値は、 では 10 進数では 10.1499996185 などと同等として 2 進数で表されますが、REAL*4では 10.15000000000000035527 などと同等です。REAL*8相互変換では、 0.625 などの正確な 2 進数値を表す少数の小数を除き、近似値が行われます。 の場合REAL*10、10 進文字列は 10.149999999999999996530553 などです。最後の 9 桁は 18 番目の小数桁であり、文字列の 20 番目の有効桁です。 80ビット形式の10進数と2進数間の変換の境界は、次のように与えられます。最大18桁の有効桁数を持つ10進文字列が(入力として)80ビットのIEEE 754 2進浮動小数点値に正しく丸められ、次に同じ有効桁数の10進数(出力として)に戻されると、最終的な文字列は元の文字列と完全に一致します。一方、逆に、80ビットのIEEE 754 2進浮動小数点値が正しく変換され、(最も近い)少なくとも21桁の有効桁数を持つ10進文字列に丸められ、次に2進形式に戻されると、元の文字列と完全に一致します。 [12]これらの近似は、任意精度の算術演算で計算される場合のように、数式内の定数に最適な値を高精度に指定するときに特に厄介です。
80ビット形式の必要性
拡張精度形式の仮数部に最低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が 1未満の場合は基数点の右側に 53 ビットが必要であり、Mが 1未満の場合は基数点の右側に 54 ビットが必要です。基数点の右側に追加される精度に対するこの要件のバランスをとると、512 未満の指数には基数点の左側に 9 ビットのみが必要となり、256 未満の指数には基数点の左側に 8 ビットのみが必要となります。
指数計算の最後の部分は、 2 つの中間結果を計算します。「中間結果」は、整数部分「I」と小数部分「F 」を加算したものです。中間結果が負の場合、「 I」と「F 」は両方とも負の数であるため、正の小数部分を取得するには若干の調整が必要です。
中間結果が肯定的である場合:
中間結果が否定的である場合:
したがって、中間結果の整数部分 (" I " または" I − 1 ")にバイアスを加えたものが最終結果の指数となり、変換された中間結果の正の小数部分 ( 2 Fまたは2 F + 1)が最終結果の仮数部となります。最終結果に 52 ビットの精度を与えるには、正の小数部分を少なくとも 52 ビットに維持する必要があります。
結論として、中間結果の仮数部に必要な正確な精度ビット数は、ある程度データに依存しますが、倍精度数値を含む指数計算の大部分で精度の低下を回避するには 64 ビットで十分です。
拡張精度形式の指数に必要なビット数は、拡張形式を使用して計算されたときに2 つの倍精度数の積がオーバーフローしないという要件に従います。倍精度値の最大可能な指数は 1023 なので、2 つの倍精度数の最大可能な積の指数は2047 (11 ビット値) です。負の指数を考慮してバイアスを追加すると、指数フィールドは少なくとも 12 ビットの幅が必要になります。
これらの要件を組み合わせると、符号に1ビット、バイアス指数に12ビット、仮数部に64ビットとなり、拡張精度形式には少なくとも77ビットが必要になります。エンジニアリング上の考慮の結果、最終的に80ビット形式が定義されました(特にIEEE 754規格では、拡張精度形式の指数範囲は、次に大きい4倍精度形式である15ビットと一致する必要があります)。[27]
拡張精度演算の恩恵を受ける計算のもう一つの例は、数値線形代数で通常行われる非常に大量の計算中に直接解に蓄積された誤差を間接的に除去するために使用される反復改良スキームである。[30]
言語サポート
- 一部のC / C++実装(GNUコンパイラコレクション(GCC)、Clang、Intel C++など)は
long double、x86システムで80ビット浮動小数点数を使用して実装しています。ただし、これは実装定義の動作であり、必須ではありませんが、C99__float80標準「Annex F IEC 60559浮動小数点演算」でIEEE 754ハードウェアに指定されているように、標準では許可されています。GCCは、および型も提供します__float128。[31] - 一部のCommon Lisp実装 (例: CMU Common Lisp、Embeddable Common Lisp )は
long-float、x86 システム上で 80 ビット浮動小数点数を使用して実装します。 - Dプログラミング言語は、ハードウェアで実装されている最大の浮動小数点サイズ (x86 CPU の場合は 80 ビット) を使用して実装します。
real他のマシンでは、CPU でネイティブにサポートされている最も広い浮動小数点型、または 64 ビットの倍精度のいずれか広い方になります。 - Turbo Pascal(およびObject PascalまたはDelphi)には、 / (32ビット)と(64ビット)
extendedに加えて、ネイティブ(80x87コプロセッサが存在する場合)またはエミュレート(Turbo87ライブラリ経由)で使用できる80ビット型があります。この型は、16ビット、32ビット、64ビットのプラットフォームで使用でき、パディングを使用できる場合もあります。[32]realsingledoubleextended - Racketランタイム システムは、x86 システムで 80 ビットの extflonum データ型を提供します。
- Swift標準ライブラリはデータ型を提供します
Float80。 - PowerBASIC BASIC コンパイラは
EXT、EXTENDED10 バイトの拡張精度浮動小数点データ型を提供します。 - Zig はバージョン 0.10.0 以降で f80 型を提供します。
参照
- GNU MPFR – C 用の GNU「信頼性の高い多倍長浮動小数点」ライブラリ
- IBM 16進浮動小数点
- IEEE754 規格
- ロングダブル
- 87 の
脚注
- ^ 「このフォーマットは主にプログラマーが単精度および倍精度ソフトウェアの整合性を高め、より大きな次元の倍精度行列計算における丸めによる劣化を軽減することを目的としており、拡張を四倍精度に置き換えてもその使用が無効にならないように簡単に使用できます。」— x87設計者W. Kahan [13]
- ^ 「高級言語では、中間部分式を評価するためにextended(目に見えない形で)を使用し、後にextendedを宣言可能なデータ型として提供する可能性がある。」[16] :70
- ^ 「拡張された数値には、それがサポートする基本形式の指数フィールドと同数以上の精度の追加ビットが存在するため、超越関数、内積、およびべき乗関数y xの正確な計算が大幅に簡素化されます。」[29] :70
参考文献
- ^ IEEE 754 (2008、¶ 2.1.21) では、拡張精度形式を「より広い精度と範囲を提供することで、サポートされている基本形式を拡張する形式」と定義しています。
- ^ Francis, CG (1965年2月11日). 「IBMが強力な小型コンピュータを発表」. 情報部長 (プレスリリース).ニューヨーク州ホワイトプレーンズ: International Business Machines Corporation (IBM). 2019年7月5日時点のオリジナルよりアーカイブ。
- ^ サブルーチンライブラリ(PDF) . IBM 1130 (第9版). IBM Corporation. 1974. p. 93.
- ^ 動作原理。IBM System/360 (第9版)。IBM Corporation。1970年、p.41。
- ^ IBM System/370 動作原理(第 7 版)。IBM Corporation。1980 年。9-2 ~ 9-3 ページ。
- ^ Steil, Michael (2008-10-20). 「6502 用の Microsoft BASIC の独自バージョンを作成する」pagetable.com . p. 46. 2016-05-30 時点のオリジナルよりアーカイブ。2016-05-30取得。
- ^ IEEE コンピュータ協会 (2008 年 8 月 29 日)。IEEE 浮動小数点演算標準 (レポート)。IEEE。§3.7。doi :10.1109 / IEEESTD.2008.4610935。ISBN 978-0-7381-5752-8IEEE 規格 754-2008。
- ^ Brewer, Kevin. 「Kevin's Report」. IEEE-754 参考資料. 2012 年 2 月 19 日閲覧。
- ^ Motorola MC68000 ファミリー(PDF)。プログラマーズリファレンスマニュアル。NXP Semiconductors。1992 年。pp. 1–16、1–18、1–23。
- ^ ColdFire ファミリ(PDF)。プログラマーズ リファレンス マニュアル。Freescale 半導体。2005 年。p. 7-7。
- ^ 「FPA10 データシート」(PDF) . chrisacorns.computinghistory.org.uk . GEC Plessey Semiconductors. 1993 年 6 月 11 日. 2020 年11 月 26 日閲覧。
- ^ ab Kahan, William (1997 年 10 月 1 日). 「2 進浮動小数点演算に関する IEEE 標準 754 の現状に関する講義ノート」(PDF)。
- ^ Kahan, William (1997 年 10 月 1 日)。「2 進浮動小数点演算に関する IEEE 標準 754 の現状に関する講義ノート」(PDF)。5 ページ。
- ^ Einarsson, Bo (2005). 科学計算における精度と信頼性。SIAM。pp. 9ff. ISBN 978-0-89871-815-7. 2013年5月3日閲覧。
- ^ 「Intel 64 および IA-32 アーキテクチャ」。ソフトウェア開発者マニュアル。Intel Corp. 2012 年 3 月。§8.2。
- ^ Coonen, Jerome T. (1980 年 1 月)。「浮動小数点演算の標準案の実装ガイド」IEEE Computer . 13 :68–79. doi :10.1109/MC.1980.1653344. S2CID 206445847。
- ^ Kahan, William (1983 年 11 月 22 日). 「砂に書かれた数学 - hp-15C、Intel 8087 など」(PDF)。
- ^ Goldberg, David (1991 年 3 月). 「すべてのコンピュータ科学者が浮動小数点演算について知っておくべきこと」(PDF) . ACM Computing Surveys . 23 (1): 192. doi :10.1145/103162.103163. S2CID 222008826.
- ^ Higham, Nicholas (2002)。「安定したアルゴリズムの設計」。数値アルゴリズムの精度と安定性(第 2 版)。工業応用数学協会 (SIAM)。p. 43。
- ^ 80C187 80ビット数値演算コプロセッサ(PDF) (データシート)。Intel Corporation。1992年11月。p.4 。 2024年8月24日閲覧。
- ^ Intel 64 および IA-32 アーキテクチャ開発者マニュアル(PDF)。第 1 巻: 基本アーキテクチャ。Intel Corporation。2024 年 6 月。§4.2.2 浮動小数点データ型、§4.8 実数と浮動小数点形式。2024年 8 月 24 日に取得。 その他の巻は、Intel® 64 および IA-32 アーキテクチャー ソフトウェア開発者マニュアルで入手できます。
- ^ パーマー、ジョン F.; モース、スティーブン P. (1984)。8087 入門。ワイリー プレス。pp. 14。ISBN 0-471-87569-4。
- ^モース、スティーブン・P. 、アルバート、ダグラス・J. (1986) 。80286アーキテクチャ。ワイリー・プレス。pp.91–111。ISBN 0-471-83185-9。
- ^ Intel 64 および IA-32 アーキテクチャ開発者マニュアル (レポート)。第 1 巻。Intel Corporation。pp . 8-21 から 8-22。
- ^ Severance, Charles (1998 年 2 月 20 日). 「浮動小数点の老舗とのインタビュー」. eecs.berkeley.edu .カリフォルニア大学バークレー校.
- ^ パーマー、ジョン F.; モース、スティーブン P. (1984)。8087 入門。ワイリー プレス。pp. 16。ISBN 0-471-87569-4。
- ^ ab モース、スティーブン P.; アルバート、ダグラス J. (1986) 。80286 アーキテクチャ。Wiley Press。pp. 96–98。ISBN 0-471-83185-9。
- ^ Hough, David (1981 年 3 月). 「浮動小数点演算のための IEEE 754 標準の提案の応用」. IEEE Computer . 14 (3): 70–74. doi :10.1109/CM.1981.220381. S2CID 14645749.
- ^ Coonen, Jerome T. (1980 年 1 月)。「浮動小数点演算の標準案の実装ガイド」IEEE Computer : 68–79. doi :10.1109/MC.1980.1653344. S2CID 206445847。
- ^ Demmel, James ; Hida, Yozo; Kahan, William ; Li, Xiaoye S. ; Mukherjee, Sonil; Riedy, E. Jason (2006 年 6 月). 「超高精度反復改良による誤差境界」(PDF) . ACM Transactions on Mathematical Software . 32 (2): 325–351. doi :10.1145/1141885.1141894. S2CID 1340891 . 2014 年 4 月 18 日閲覧。
- ^ 「浮動小数点型(GNU コンパイラ コレクション(GCC)の使用)」。
- ^ 「拡張データ型はプラットフォームによって異なります」。
