テヌブルメヌカヌのゞレンマ、たたはほずんどすべおの超越的な基本機胜が間違っおいる理由

珟代のコンパむラで䜿甚されおいる数孊ラむブラリが正しく䞞められた結果をもたらさないこずがあるこずを気にする人がほずんどいないかのように、ロシア語でこの問題に関する情報を芋぀けるのが難しいこずに驚きたした。私はそのような数孊的ラむブラリの開発に取り組んでいるだけなので、この状況が心配です。倖囜の文献では、この問題は十分にカバヌされおいるので、西掋の情報源ずただ少し個人的な経隓に頌っお、人気のある科孊的な圢でロシア語でそれを提瀺するこずにしたした。






友だち、あなたの䟿宜のために、蚘事はビデオプレれンテヌション圢匏玄34分でも利甚できたす。この圢匏は、プレれンテヌションに倚くの説明資料があるため、頭の䞭で必芁な数孊的画像を䜜成するのが難しい読者に適しおいたす。ビデオの情報は、蚘事の内容ず完党に同じです。ご郜合の良いずきに行動しおください。








これは科孊的なものではなく、人気のある科孊的な蚘事であるこずを繰り返したす。これを読んだ埌、簡単にこれを知るこずができたす。



  • 浮動小数点挔算で機胜する超越的な基本関数exp、sin、log、coshなどは正しく䞞められず、最埌のビットで゚ラヌが発生するこずがありたす。
  • ゚ラヌの理由は、必ずしも開発者の怠惰や資栌の䜎さにあるずは限りたせんが、珟代科孊がただ克服できおいない1぀の基本的な状況にありたす。
  • «», - .
  • , , , , exp2(x) pow(2.0, x).


この蚘事を理解するには、IEEE-754フロヌティングポむント圢匏に粟通しおいる必芁がありたす。たずえば、これが次のずおりであるこずを少なくずも理解しおいれば十分です。0x400921FB54442D18-2倍粟床圢匏binary64、たたはdoubleの数倀pi、぀たり、このレコヌドの意味を理解しおいるだけです。私はそのような倉換をその堎で行うこずができるこずを芁求したせん。そしお、この蚘事の䞞めモヌドに぀いお思い出させたす。これはストヌリヌの重芁な郚分です。西掋の文孊からの甚語や匕甚があるので、「プログラマヌ」の英語を知っおいるこずも望たしいですが、あなたはオンラむン翻蚳者ず䞀緒にやっおいくこずができたす。



最初に䟋を挙げお、䌚話の䞻題が䜕であるかをすぐに理解できるようにしたす。ここでコヌドをC ++で瀺したすが、これがあなたの蚀語でない堎合でも、曞かれおいるこずを簡単に理解できるず確信しおいたす。このコヌドを芋おください



#include <stdio.h>
#include <cmath>

int main() {
  float x = 0.00296957581304013729095458984375f;  // ,  .
  float z;
  z = exp2f(x);  // z = 2**x  .
  printf ("%.8f\n", z);  //      8   .
  z = powf(2.0f, x);  // z = 2**x  
  printf ("%.8f\n", z);  //   .
  return 0;
}


数倀xは、floatタむプで正確に衚珟できるように、぀たり、コンパむラヌが䞞めずにバむナリコヌドに倉換するように、意図的にこのような有効桁数で蚘述されおいたす。結局のずころ、䞀郚のコンパむラぱラヌなしで䞞めるこずができないこずをよく知っおいたすわからない堎合は、コメントで瀺しおください。䟋を含む別の蚘事を䜜成したす。次にプログラムで2xを蚈算する必芁がありたすが、2぀の方法で蚈算したしょう。関数exp2fxず、2぀のpowf2.0f、xの明瀺的な指数です。もちろん、結果は異なりたす。これは、基本機胜がすべおの堎合に正しく機胜するずは限らないこずを前述したため、これを瀺すために特別に䟋を遞択したした。出力は次のずおりです。



1.00206053
1.00206041


Microsoft C ++19.00.23026、Intel C ++ 15.0、GCC6.3.0、Clang3.7.0の4぀のコンパむラヌからこれらの倀が埗られたした。それらは1぀の最䞋䜍ビットが異なりたす。これらの数倀の16進コヌドは次のずおりです。



0x3F804385  // 
0x3F804384  // 


この䟋を芚えおおいおください。少し埌で問題の本質を芋おいきたすが、今のずころ、より明確な印象を埗るために、他のいく぀かの基本関数を䜿甚した倍粟床デヌタタむプdouble、binary64の䟋を参照しおください。結果を衚に瀺したす。正解利甚可胜な堎合の最埌に*が付いおいたす。



関数 匕数 MS C ++ Intel C ++ Gcc クラン
log10x 2.60575359533670695e129 0x40602D4F53729E44 0x40602D4F53729E45 * 0x40602D4F53729E44 0x40602D4F53729E44
expm1x -1.31267823646623444e-7 0xBE819E53E96DFFA9 * 0xBE819E53E96DFFA8 0xBE819E53E96DFFA8 0xBE819E53E96DFFA8
パり10.0、x 3.326929759608827789e-15 0x3FF0000000000022 0x3FF0000000000022 0x3FF0000000000022 0x3FF0000000000022
logp1x -1.3969831951387235e-9 0xBE17FFFF4017FCFF * 0xBE17FFFF4017FCFE 0xBE17FFFF4017FCFE 0xBE17FFFF4017FCFE




私がわざず芋぀けられないような完党にナニヌクなテストを行ったずいう印象を受けないでください。もしそうなら、floatデヌタタむプの2x関数のすべおの可胜な分数匕数の完党な列挙をひざたずいおみたしょう。他の匕数は指数フィヌルドの倀のみが異なり、関心のない結果をもたらすため、0から1の間のxの倀のみに関心があるこずは明らかです。あなた自身が理解しおいたす

2x=2[x]⋅2{x}..。





そのようなプログラムを曞いた埌非衚瀺のテキストは以䞋にありたす、exp2f関数ず、0から1たでの間隔xで生成される誀った倀の数を確認したした。



MS C ++ Intel C ++ Gcc クラン
1,910,7260.97 902310.05 0 0




以䞋のプログラムから、テストされた匕数xの数が197612997であったこずが明らかです。たずえば、Microsoft C ++は、それらのほが1パヌセントに぀いお2x関数を誀っお蚈算しおいるこずがわかりたした。GCCずClangのファンの皆さん、喜ばないでください。この関数がこれらのコンパむラで正しく実装されおいるだけですが、他のコンパむラでぱラヌがいっぱいです。



ブルヌトフォヌスコヌド
#include <stdio.h>
#include <cmath>

    //         float  double
#define FAU(x) (*(unsigned int*)(&x))
#define DAU(x) (*(unsigned long long*)(&x))

    //    2**x      0<=x<=1.
    //  , ,    ,  
    //     10- .
    //     double (     ).
    //        FMA-, 
    //  ,   , ...   .
float __fastcall pow2_minimax_poly_double (float x) {
  double a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
  DAU(a0) = 0x3ff0000000000001;
  DAU(a1) = 0x3fe62e42fefa3763;
  DAU(a2) = 0x3fcebfbdff845acb;
  DAU(a3) = 0x3fac6b08d6a26a5b;
  DAU(a4) = 0x3f83b2ab7bece641;
  DAU(a5) = 0x3f55d87e23a1a122;
  DAU(a6) = 0x3f2430b9e07cb06c;
  DAU(a7) = 0x3eeff80ef154bd8b;
  DAU(a8) = 0x3eb65836e5af42ac;
  DAU(a9) = 0x3e7952f0d1e6fd6b;
  DAU(a10)= 0x3e457d3d6f4e540e;
  return (float)(a0+(a1+(a2+(a3+(a4+(a5+(a6+(a7+(a8+(a9+a10*x)*x)*x)*x)*x)*x)*x)*x)*x)*x);
} 

int main() {
  unsigned int n = 0;  //  .
  //      x   (0,1)
  //  : 0x33B8AA3B = 0.00000008599132428344091749750077724456787109375
  //   ,   2**x > 1.0f
  //  : 0x3F800000 = 1.0 .
  for (unsigned int a=0x33B8AA3B; a<0x3F800000; ++a) {  
   float x;
    FAU(x) = a;
    float z1 = exp2f (x);	//  .
    float z2 = pow2_minimax_poly_double (x);	//  .
    if (FAU(z1) != FAU(z2)) {	//  .
      //  ,        (   ).
      //fprintf (stderr, "2**(0x%08X) = 0x%08X, but correct is 0x%08X\n", a, FAU(z1), FAU(z2));
      ++n;
    }		
  }
  const unsigned int N = 0x3F800000-0x33B8AA3B;  //     .
  printf ("%u wrong results of %u arguments (%.2lf%%)\n", n, N, (float)n/N*100.0f);
  return 0;
} 




私はこれらの䟋で読者を退屈させたせん。ここでの䞻なこずは、超越関数の最新の実装が最埌のビットを誀っお䞞めるこずができ、さたざたなコンパむラがさたざたな堎所で間違いを犯す可胜性があるこずを瀺すこずでしたが、どれも正しく機胜したせん。ちなみに、IEEE-754暙準では最埌のビットでこの゚ラヌが蚱可されおいたすがこれに぀いおは埌で説明したす、それでも私には奇劙に思えたす。これは倧きなデヌタタむプですが、フロヌトはブルヌトフォヌスでチェックできたす。そんなに倧倉でしたかたったく難しいこずではありたせん、そしお私はすでに䟋を瀺したした。



私たちの列挙コヌドには、正しい蚈算の「自己蚘述」関数が含たれおいたす2 x10次​​の近䌌倚項匏を䜿甚し、そのような倚項匏は、たずえばMapleコンピュヌタ代数システムで自動的に導出されるため、数分で蚘述されたした。倚項匏の条件を蚭定しお54ビットの粟床を提䟛するだけで十分ですこの関数の堎合、2 x。なぜ54しかし、問題の本質を説明し、理論的にはこの問題を攻撃する詊みはすでに行われおいたすが、原則ずしお、4倍粟床のデヌタタむプbinary128に察しお高速で正確な超越関数を䜜成するこずが䞍可胜である理由を説明した盎埌にすぐにわかりたす。



デフォルトの䞞めずその問題



数孊ラむブラリの開発に没頭しおいない堎合は、IEEE-754暙準に準拠した浮動小数点数のデフォルトの䞞め芏則を忘れおも問題はありたせん。したがっお、私はあなたにそれを思い出させたす。すべおをよく芚えおいるなら、ずにかく少なくずもこのセクションの終わりを芋おください、あなたは驚きに満ちおいたす私はあなたに数を切り䞊げるこずが非垞に難しいかもしれない状況をあなたに芋せたす。



「切り䞊げ」プラスの無限倧ぞ、「切り䞋げ」マむナスの無限倧ぞ、「れロぞの䞞め」を名前で簡単に思い出すこずができたすどちらかずいえば、りィキペディアがありたす。プログラマヌにずっおの䞻な問題は、「最も近いものに䞞めるが、最も近いものから等しい距離の堎合、最埌の桁が偶数であるものに」䞞めるこずで発生したす。はい、これはこの䞞めモヌドがどのように倉換されるかであり、西掋の文献は芁するに「最も近いものを偶数に䞞める」ず呌んでいたす。



この䞞めモヌドはデフォルトで䜿甚され、次のように機胜したす。蚈算の結果、マンティッサの長さが結果のデヌタタむプに察応できる長さよりも長いこずが刀明した堎合、2぀の可胜な倀の最も近い倀に䞞めが実行されたす。ただし、元の数倀が最も近い2぀の数倀のちょうど䞭間にあるこずが刀明した堎合、最埌のビット䞞め埌が偶数、぀たりれロに等しい結果が遞択される堎合がありたす。バむナリ小数点の埌に2ビットに䞞める必芁がある4぀の䟋を考えおみたしょう。



  1. 1.00 1 001を䞞めたす。小数点以䞋の3番目のビットは1ですが、別の6番目のビットである1がありたす。これは、元の数倀が1.00よりも1.01に近いため、䞞めが䞊がるこずを意味したす。
  2. 1,001000. , 1,00 1,01, .
  3. 1,011000. 1,01 1,10. , .
  4. 1,010111. , 1,01, 1,10.


これらの䟋から、すべおが単玔に芋えるかもしれたせんが、そうではありたせん。実際には、2぀の倀の䞭間にあるかどうかを確実に刀断できない堎合がありたす。䟋を参照しおください。我々は再び小数点以䞋2ビットにラりンドしたいずし



1.00 1 0000000000000000000000000000000000001



䞞めが数1.01に、あるこず、アップであるこずを今、あなたには自明です。ただし、小数点以䞋40ビットの数倀を芋おいたす。アルゎリズムが40ビットの粟床を提䟛できず、30ビットしか達成できない堎合はどうなりたすかそれからそれは別の数を䞎えるでしょう



1.00 1 000000000000000000000000000



40番目の䜍眮アルゎリズムでは蚈算できたせんに倧切なものがあるこずに気づかずに、この数倀を切り捚おお1.00を取埗したすが、これは間違っおいたす。あなたは最埌のビットを間違っお切り䞊げたした-それが私たちの議論の䞻題です。䞊蚘のこずから、2番目のビットだけを正しくするためには、最倧40ビットの関数を蚈算する必芁があるこずがわかりたす。うわヌそしお、れロの「機関車」がさらに長くなるこずが刀明した堎合はどうなりたすかこれに぀いおは、次のセクションで説明したす。



ちなみに、これは倚くのコンパむラが浮動小数点数の10進衚蚘を結果のバむナリ圢匏に倉換するずきに犯す間違いです。プログラムコヌドの元の10進数が、正確に衚珟できる2぀のバむナリ倀の䞭間に近すぎるず、正しく䞞められたせん。しかし、これはこの蚘事のトピックではなく、別の話の理由です。



最埌の重芁なビットを䞞める問題の本質



この問題は2぀の理由で珟れたす。1぀目は、時間のかかる蚈算を意図的に拒吊し、速床を優先するこずです。この堎合、指定された粟床が守られおいる限り、応答にどのビットが含たれるかは二次的な問題です。2番目の理由は、私たちの䌚話の䞻芁な䞻題であるテヌブルメヌカヌのゞレンマです。䞡方の理由をさらに詳しく考えおみたしょう。



最初の理由



もちろん、超越関数の蚈算は、いく぀かの近䌌方法、たずえば、倚項匏を近䌌する方法、たたはたれに系列展開によっお実装されるこずを理解しおいたす。蚈算をできるだけ早く行うために、開発者は、アルゎリズムがマンティッサの最埌のビットの倀の半分を超えない゚ラヌを蚱可する限り、数倀メ゜ッドの反埩をできるだけ少なく実行するたたは可胜な限り最小の倚項匏を取るこずに同意したす。文献では、これは0.5ulpず曞かれおいたすulp =最埌の単䜍。



たずえば、間隔0.5; 1内のfloat型の数xに぀いお話しおいる堎合、倀ulp = 2-23です。間隔1; 2でulp = 2-22。蚀い換えるず、xが間隔0; 1にある堎合、2 xは間隔1,2にあり、0.5ulpの粟床を確保するには、倧たかに蚀えば、EPS = 2 -23を遞択する必芁がありたすしたがっお、「゚ラヌ」たたは「粟床」ず呌ばれる䞀般の人々では、定数「むプシロン」を瀺したす。あなたが奜きなように、欠点を芋぀けないでください。



適甚される蚈算の堎合、これで十分ですが、最埌のビットが絶察結果ず䞀臎しない可胜性があるずいう事実は、ほずんどのプログラマヌにずっお重芁ではありたせん。ビットが䜕であるかではなく、粟床がどうなるかが重芁だからです。



わからない方のために、10進数制の䟋をあげたす。 1.999999ず2.0の2぀の数倀がありたす。 1぀目はプログラマヌが受け取ったものであり、2぀目は無限の可胜性があった堎合に埗られるべきものの暙準であるずしたしょう。それらの違いはわずか100䞇分の1です。぀たり、回答はEPS = 10-6で蚈算されたした。ただし、この回答には正しい番号は1぀ではありたせん。悪いですかいいえ、アプリケヌションプログラムの芳点からは、これは玫色です。プログラマヌは答えを小数点以䞋2桁に切り䞊げお、2.00たずえば、通貚に぀いおの$ 2.00を取埗したす。これ以䞊は必芁ありたせんが、圌が私のプログラムにEPS = 10 -6を入れお、それでうたくいき、䞭間蚈算の゚ラヌのマヌゞンを取り、問題を正しく解決したした。



蚀い換えれば、混同しないでください。正しいビットたたは桁の粟床ず数は2぀の異なるものです。正確さが必芁な人これはほが100のプログラマヌです、議論された問題はそれらにはたったく関係ありたせん。正しく䞞められた参照に䞀臎するためにビットシヌケンスを必芁ずする人は誰でも、たずえば、基本関数のラむブラリの開発者など、この問題に぀いお非垞に心配しおいたす。それにもかかわらず、䞀般的な開発のためにこれに぀いお知っおいるこずは誰にずっおも有甚です。



これが問題の最初の方向であったこずを思い出させおください。これは意図的な解決策であるため、答えの最埌の郚分が間違っおいる可胜性がありたす。䞻なこずは、0.5ulpたたはそれ以䞊の粟床を維持するこずです。したがっお、数倀アルゎリズムは、それが非垞に高速に機胜する堎合にのみ、この条件からのみ遞択されたす。同時に、この芏栌では、最埌のビットを正しく䞞めるこずなく、基本関数を実装できたす。私は[1、セクション12.1]英語を匕甚したす

浮動小数点挔算に関するIEEE754暙準の1985バヌゞョンでは、基本機胜に関しお䜕も指定されおいたせんでした。これは、正しく䞞められた関数は、少なくずも䞀郚の入力匕数に察しおは遅すぎるず長幎信じられおきたためです。それ以来状況は倉化し、2008幎版の芏栌では、䞀郚の関数を正しく䞞めるこずを掚奚しおいたすただし必須ではありたせん。



以䞋は、掚奚されおいるが正しく䞞める必芁のない関数です。



機胜リスト




2番目の理由



最埌に、䌚話のトピックに到達したしたテヌブルメヌカヌのゞレンマTMDず略されたす。その名前をロシア語に適切に翻蚳するこずはできたせんでした。それはWilliamKahanIEEE-754の創蚭者によっお蚘事[2]で玹介されたした。おそらく蚘事を読めば、その名前がたさにそれである理由を理解するでしょう。芁するに、ゞレンマの本質は、完党に蚈算された結果zの無限ビットレコヌドを自由に䜿甚できるかのように、関数z = fxを完党に正確に䞞める必芁があるずいうこずです。しかし、無限のシヌケンスを取埗できないこずは誰にずっおも明らかです。それでは䜕ビットかかりたすか䞊蚘では、䞞め埌に少なくずも2぀の正しいビットを取埗するために、結果の40ビットを確認する必芁がある堎合の䟋を瀺したした。そしお、TMD問題の本質は、事前にわからないずいうこずです。、必芁な数の䞞め埌に正しいビット数を取埗するために、zの倀を蚈算するビット数たで。癟たたは千がある堎合はどうなりたすか事前にはわかりたせん



たずえば、前述したように、関数2 xの堎合、マンティッサの分数郚分が23ビットしかないデヌタ型floatの堎合、䟋倖なくすべおの可胜なx匕数に察しお正しく䞞めが行われるように、2-54の粟床で蚈算を実行する必芁がありたす。培底的な怜玢でこの掚定倀を取埗するこずは難しくありたせんが、他のほずんどの関数、特にタむプdoubleたたはlong doubleそれが䜕であるかを知っおいる堎合は「クラス」ず入力の堎合、そのような掚定倀は䞍明です。



なぜこれが起こっおいるのかをすでに理解したしょう。この蚘事の最初の䟋ずしおfloatデヌタタむプを意図的に瀺し、芚えおおいおもらいたした。このタむプでは32ビットしかないため、芋やすくなりたす。他のデヌタタむプでも状況は䌌おいたす。



数倀x = 0.00296957581304013729095458984375から始めたした。これは、floatデヌタタむプで正確に衚珟できる数倀です。぀たり、䞞めるこずなくバむナリfloatシステムに倉換できるように蚘述されおいたす。 2 xを蚈算し、無限の粟床の蚈算機がある堎合は、次のようになりたす確認できるように、蚈算はオンラむンのWolframAlphaシステムで行われたす



1.0020604729652405753669743044108123031635398201893943954577320057 .. ..



レッツの64ビットは十分でしょう蚀わせお、バむナリにこの番号を倉換



1.00000000100001110000100 1 000000000000000000000000000001101111101



䞞めビット小数点以䞋24ビットは䞋線が匕かれおいたす。質問どこを䞞めるのですか䞊か䞋明らかに、あなたは十分なビットを芋お決定を䞋すこずができるので、これを知っおいたす。しかし、泚意深く芋おください...



䞞めビットの埌、29個のれロがありたす。これは、最も近い2぀の数倀の䞭間に非垞に近く、䞞めの方向が倉わるため、少し䞋に移動するだけで十分であるこずを意味したす。しかし、問題は、このシフトはどこにあるのかずいうこずです。数倀アルゎリズムは、段階的に、さたざたな偎面から正確な倀に近づくこずができたす。これらの29個のれロをすべお通過し、この「機関車」の最埌のれロの倀を超える粟床に達するたで、䞞めの方向はわかりたせん。 ..。実際、正解が次のようになっおいる堎合はどうなりたすか



1.00000000100001110000100 0 11111111111111111111111111111



その埌、䞞めがダりンしたす。



粟床が小数点以䞋54ビットに達するたでこれはわかりたせん。 54番目のビットが正確にわかっおいる堎合、2぀の最も近い数倀のどちらが実際に近いかを正確に知るこずができたす。そのような番号が呌び出される最も困難なツヌ䞞点[1、セクション12.3䞞めのための重芁な点、及び数54が呌び出され、硬床察ラりンド、および匕甚した曞籍の文字Mで瀺されおいたす。



䞞めの耇雑さmは、特定の関数fxのすべおの匕数に぀いお、および事前に遞択された範囲に぀いお、関数fxが最埌のビットに正しく䞞められるようにするために必芁な最小ビット数です䞞めモヌドが異なるず、異なる堎合がありたす倀m。蚀い換えるず、デヌタ型floatの堎合、および䞞めモヌドの範囲0; 1から「最も近い偶数」の䞞め時間m = 54たでの匕数xの堎合。これは、間隔0; 1からの絶察にすべおのxに぀いお、同じ粟床のESP = 2 -54をアルゎリズムに入れるこずができ、すべおの結果が2進小数点以䞋23ビットに正しく䞞められるこずを意味したす。



実際、䞀郚のアルゎリズムは正確な結果を提䟛でき、53ビットおよび52ビットに基づいお、ブルヌトフォヌスがこれを瀺したすが、理論的には正確に54が必芁です。ブルヌトフォヌスをクランクアりトする可胜性がなければ、「チヌト」するこずはできたせん。䞊蚘のブルヌトフォヌスプログラムで行ったように、2、3ビット節玄したす。必芁以䞊に䜎い次数の倚項匏を取りたしたが、運が良かったずいう理由だけで、それでも機胜したす。



したがっお、䞞めモヌドに関係なく、2぀の状況が考えられたす。䞞め領域でれロの「蒞気機関車」が発生するか、1の「蒞気機関車」が発生したす。超越関数fxを蚈算するための正しいアルゎリズムのタスクは、粟床がこの「蒞気機関車」の最埌のビットの倀を超えるたで、そしおfを蚈算するための数倀アルゎリズムのその埌の倉動の結果ずしお正確に明らかになるたで、この関数の倀を改良するこずです。 xれロは1になりたせん、たたはその逆です。すべおが安定し、アルゎリズムが「蒞気機関車」の限界を超える粟床に達するずすぐに、ビット数が無限であるかのように䞞めるこずができたす。そしお、この䞞めは正しい最埌のビットで行われたす。しかし、これはどのように達成できたすか



「クラッチ」



前述のように、䞻な問題は、䞞めビットの盎埌に来る0たたは1の機関車を克服するためのアルゎリズムを取埗するこずです。機関車が克服され、党䜓ずしお芋るず、これは、これらの0たたは1がすでに正確に蚈算されおおり、䞞めがどの方向で発生するかを正確に知っおいるずいう事実ず同等です。しかし、機関車の長さがわからない堎合、どのようにアルゎリズムを蚭蚈できたすか



最初の「クラッチ」



答えは明癜であるように読者には思われるかもしれたせん。無限の粟床で算術を取り、意図的に過剰なビット数を入れ、それが十分でない堎合は、別のビットを入れお再蚈算したす。䞀般的に、それは正しいです。これは、コンピュヌタヌの速床ずリ゜ヌスが特別な圹割を果たさない堎合に行われたす。このアプロヌチには名前がありたすZivのマルチレベル戊略[1、セクション12.3]。その本質は非垞に単玔です。アルゎリズムは、いく぀かのレベルでの蚈算をサポヌトする必芁がありたす。迅速な予備蚈算ほずんどの堎合、最終的なものであるこずが刀明、䜎速ですがより正確な蚈算最も重芁な堎合に保存、さらに䜎速ですが、さらに正確な蚈算絶察に「悪い堎合」 「しなければならなかったなど。



圧倒的倚数の堎合、0.5ulpより少し高い粟床で十分ですが、「機関車」が出おきたら䞊げたす。 「蒞気機関車」が残っおいる限り、数倀法のさらなる倉動がこの「蒞気機関車」に圱響を䞎えないこずが厳密に明らかになるたで、粟床を䞊げたす。したがっお、たずえば、この堎合、ESP = 2 -54に達した堎合、54番目の䜍眮にナニットが衚瀺されたす。これは、いわば、機関車をれロから「保護」し、2-53以䞊の倀の枛算が発生しないこずを保蚌したす。れロは1にならず、䞞めビットをれロにドラッグしたす。



これは人気のある科孊プレれンテヌションであり、Zivの䞞めテストず同じです。このテストでは、[1、第12ç« ]、たたは[3、セクション]で、必芁な粟床を達成したかどうかを1぀のステップで確認する速床が瀺されおいたす。 10.5]。



このアプロヌチの問題は明らかです。各超越関数fxを蚈算するためのアルゎリズムを蚭蚈する必芁がありたす。これにより、ピヌスの過皋で蚈算の粟床を高めるこずができたす。゜フトりェアの実装の堎合、これはただそれほど怖いものではありたせん。たずえば、ニュヌトンの方法では、倧たかに蚀えば、各反埩で小数点以䞋の正確なビット数を2倍にするこずができたす。 「十分」になるたで2倍にするこずができたすが、これはかなり時間のかかるプロセスですが、逆関数f -1を蚈算する必芁があるため、ニュヌトンの方法が垞に正圓化されるずは限らないこずを認めなければなりたせん。x、堎合によっおは、fx自䜓を蚈算するよりも簡単ではない堎合がありたす。ハヌドりェアの実装では、「Ziva戊略」は完党に䞍適切です。プロセッサに組み蟌たれたアルゎリズムは、すでに事前蚭定されたビット数で䞀連のアクションを実行する必芁がありたす。この数が事前にわからない堎合、これを実装するのは非垞に問題がありたす。株匏を取りたすいくら



問題を解決するための確率論的アプロヌチ[1、セクション12.6]により、mの倀を掚定するこずができたすこれはビット数であり、正しい䞞めに十分であるこずを忘れないでください。確率的な意味での「機関車」の長さは、数のマンティッサの長さよりわずかに長いこずがわかりたす。したがっお、ほずんどの堎合、mはマンティッサの倀の2倍匷を取るだけで十分であり、ごくたれなケヌスでのみ、さらに倚く取る必芁がありたす。私はこの䜜品の䜜者を匕甚したす「実際には、mは2pよりわずかに倧きくなければならない」圌らはpを持っおいたす-敎数郚分ず䞀緒にマンティッサの長さ、぀たりフロヌトの堎合はp = 24。さらに本文では、そのような戊略での゚ラヌの確率はれロに近いが、それでも正であるこずが瀺され、これは実隓によっお確認されおいたす。



それでもなお、mの倀をさらにずらなければならない堎合があり、最悪の堎合は事前にわかっおいたせん。最悪の堎合の理論的な掚定倀は存圚したすが[1、セクション12.7.2]、それらは考えられない数癟䞇のビットを生成したす。これは良くありたせん。これは匕甚された䜜業からの衚ですこれは-ln2からln2たでの間隔での関数expx甚です



p m
24binary32 1865828
53binary64 6017142
113binary128 17570144




2番目の「クラッチ」



実際には、mはそれほど倧きくはありたせん。そしお、最悪のケヌスを決定するために、「培底的な事前蚈算」ず呌ばれる2番目の「クラッチ」が適甚されたす。デヌタタむプfloat32ビットの堎合、関数fに1぀の匕数xがあるず、xのすべおの可胜な倀を簡単に「実行」できたす。この問題は、耇数の匕数powx、yの䞭でを持぀関数でのみ発生したす。そのため、そのようなこずは考えられたせんでした。 xのすべおの可胜な倀を確認した埌、各関数fxおよび各䞞めモヌドの定数mを蚈算したす。次に、ハヌドりェアに実装する必芁のある蚈算アルゎリズムは、2- mの粟床を提䟛するように蚭蚈されおいたす。そうすれば、fxの䞞めはすべおの堎合に正しいこずが保蚌されたす。



ダブルタむプ64ビットの堎合、単玔な列挙はほずんど䞍可胜です。しかし、圌らは敎理しおいたすしかし、どのように答えは[4]にありたす。それに぀いお簡単に説明したす。



関数fxのドメむンは非垞に小さなセグメントに分割されおいるため、各セグメント内でfxをb-ax圢匏の線圢関数に眮き換えるこずができたすもちろん、係数aずbはセグメントごずに異なりたす。これらのセグメントのサむズは分析的に蚈算されるため、このような線圢関数は実際には各セグメントの元の関数ずほずんど区別できたせん。



次に、スケヌリングずシフトの操䜜を行った埌、次の問題が発生したす。盎線のb-axを敎数点に「十分に近づける」こずができるでしょうか。



はいたたはいいえの答えを出すのは比范的簡単であるこずがわかりたす。぀たり、朜圚的に危険なポむントが盎線に近い堎合は「はい」、原則ずしおそのようなポむントが盎線に近づかない堎合は「いいえ」です。この方法の利点は、実際には圧倒的倚数のケヌスで「いいえ」の回答が埗られ、めったに埗られない「はい」の回答が、どの特定のポむントが重芁であるかを刀断するために培底的な怜玢でセグメントを通過するこずを匷制するこずです。



それでも、fxの匕数の繰り返しは䜕床も削枛され、doublebinary64やlong double80ビットなどの数倀のブレヌクポむントを怜出できたす。これは、スヌパヌコンピュヌタヌ、そしおもちろんビデオカヌドで行われたす...マむニングからの自由な時間に。ただし、binary128デヌタタむプをどうするかはただ誰にもわかりたせん。そのような数のマンティッサの分数郚分は112ビットであるこずを思い出させおください。したがっお、この䞻題に関する倖囜の文献では、「私たちは垌望する...」「私たちは垌望する...」で始たる半哲孊的な掚論しか芋぀けるこずができたせん。



敎数点の近くの線の通過をすばやく決定できる方法の詳现は、ここでは䞍適切です。プロセスを孊びたい方のために、私は盎線ずZの間の距離芋぀ける問題に向けお、より慎重に探しおお勧め2を蚘事に、䟋えば、[5]。改良されたアルゎリズムに぀いお説明したす。これは、構築の過皋で、最倧の共通陀数を芋぀けるための有名なナヌクリッドのアルゎリズムに䌌おいたす。 [4]ず[5]から同じ図を瀺したす。



画像



これは、問題のさらなる倉換を瀺しおいたす。超越関数ごずに異なる間隔で䞞める最悪のケヌスを含む広範なテヌブルがありたす。それらは[1セクション12.8.4]ず[3、セクション10.5.3.2]、および別の蚘事、たずえば[6]にありたす。



そのようなテヌブルからランダムな行を取埗しお、いく぀かの䟋を瀺したす。これらはすべおのxにずっお最悪のケヌスではないこずを匷調したすが、ごく䞀郚の間隔でのみです。興味がある堎合は゜ヌスを参照しおください。



関数 バツ fxトリミング 53ビット目以降
log2x 1.B4EBE40C95A01P0 1.8ADEAC981E00DP-1 10 53 1011..。
コッシュx 1.7FFFFFFFFFFF7P-23 1.0000000000047P0 11 89 0010..。
ln1 + x 1.8000000000003P-50 1.7FFFFFFFFFFFEP-50 10 99 1000..。




衚の読み方は倀xは、16進浮動小数点の二重衚蚘で指定されたす。最初に、予想どおり、先頭に1぀あり、次にマンティッサの小数郚分の52ビットず文字Pがありたす。この文字は、「2の环乗」の埌に床が続くこずを意味したす。たずえば、P-23は、指定されたマンティッサに2-23を掛ける必芁があるこずを意味したす。



さらに、関数fxが無限の粟床で蚈算され、最初の53ビットが䞞めなしで切り取られるず想像しおください。 fx列に瀺されおいるのは、これらの53ビットそのうちの1぀はコンマたでです。埌続のビットは最埌の列に瀺されおいたす。最埌の列のビットシヌケンスの「次数」蚘号は、ビットの繰り返し回数を意味したす。぀たり、たずえば10 531011は、最初に1に等しいビット、次に53個のれロ、次に1011になるこずを意味したす。次に、省略圢。これは、䞀般に、残りのビットをたったく必芁ずしないこずを意味したす。



さらに、それは技術の問題です-別々に取られた関数の各間隔の最悪のケヌスを知っおおり、この間隔に察しお、最悪のケヌスを正確にカバヌするような近䌌を遞択できたす。わずか数幎のスヌパヌコンピュヌタヌコンピュヌティングで、基本機胜の高速で正確なハヌドりェア実装を䜜成するこずが可胜です。問題は小さいです。少なくずもコンパむラ開発者にこれらのテヌブルを䜿甚するように教えるこずは残っおいたす。



なぜこれが必芁なのですか



玠晎らしい質問です結局のずころ、プログラマヌのほが100は、正しく䞞められた最埌のビット内で基本関数を知る必芁がない倚くの堎合、ビットの半分も必芁ないず繰り返し話したしたが、なぜ科孊者はスヌパヌコンピュヌタヌを駆動し、テヌブルをコンパむルしお「圹に立たない」問題を解決するのですか



たず、課題は基本です。正確な䞞めのために正確な䞞めを取埗しないこずはかなり興味深いですが、原則ずしお、この興味深い問題をどのように解決できるかを理解するために、その解決策が私たちに明らかにする蚈算数孊の秘密は䜕ですかこれらの秘密を他のタスクでどのように䜿甚できたすか基瀎科孊-そのようなものです。䜕十幎もの間、ある皮の「ナンセンス」を行うこずができたす。その埌、100幎埌、この「ナンセンス」のおかげで、他の分野で科孊的な進歩が起こりたす。



第二に、コヌドの移怍性の問題。関数が結果の最埌のビットを必芁な方法で凊理できる堎合、それは、異なるプラットフォヌムおよび異なるコンパむラヌで、わずかに異なる結果が埗られる可胜性があるこずを意味したす指定された゚ラヌ内であっおも。これは重芁でない堎合もありたすが、特にプログラムに1぀のプラットフォヌムに衚瀺される゚ラヌが含たれおいるが、結果のビットが異なるために別のプラットフォヌムには衚瀺されない堎合は、重芁な堎合がありたす。しかし、なぜ私はあなたに異なるプログラムの振る舞いに関連するよく知られた頭痛を説明しおいるのですかあなたは私なしでこれをすべお知っおいたす。どのようにコンパむルされおいおも、すべおのプラットフォヌムでたったく同じように機胜する数孊システムがあれば玠晎らしいず思いたす。このためにあなたは正しくする必芁がありたす 最埌のビットを䞞めたす。



゜ヌスのリスト



[1] Jean-Michel Muller、「基本関数アルゎリズムず実装」、2016幎



[2] William Kahan、「察数が半分賢すぎる」、2004幎



[3] Jean-Michel Muller、「浮動小数点挔算のハンドブック」 、2018



[4]VincentLefÚvre、Jean-Michel Muller、「正しく䞞められた超越に向けお」、IEEE TRANSACTIONS ON COMPUTERS、VOL。47、いいえ。1998幎11月11日。pp。1235-1243



[5] VincentLefÚvre 。「セグメントずZずの間の距離に新しい結果2」。正確な䞞めぞの適甚。コンピュヌタ算術に関する第17回IEEEシンポゞりム-Arith'17、2005幎6月、ケヌプコッド、マサチュヌセッツ州、

アメリカ合衆囜。pp.68-75



[6]VincentLefÚvre、Jean-Michel Muller、「倍粟床での基本関数の正しい䞞めの最悪のケヌス」、Rapport de rechercheINSTITUT NA TIONAL DE RECHERCHE EN INFORMA TIQUE ET EN AUTOMA TIQUEn˚4044-2000幎11月- 19ペヌゞ。



All Articles