問題タブ [extended-precision]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c - Clang が過剰な浮動小数点精度を処理する方法を説明するドキュメントはありますか?
使用が許可されている浮動小数点命令が 387 命令のみである場合、妥当なコストで厳密な IEEE 754 セマンティクスを提供することはほぼ不可能です (*)。FPU を完全な 64 ビット仮数で動作させ続けて、long double
型を拡張精度で使用できるようにしたい場合は、特に困難です。通常の「解決策」は、利用可能な唯一の精度で中間計算を行い、多かれ少なかれ明確に定義された場合に低い精度に変換することです。
GCC の最近のバージョンは、Joseph S. Myers が2008 年の GCC メーリング リストへの投稿で提示した解釈に従って、中間計算で過剰な精度を処理します。この記述は、gcc -std=c99 -mno-sse2 -mfpmath=387
私が理解している限り、最後のビットまで完全に予測可能でコンパイルされたプログラムを作成します。偶然そうでない場合、それはバグであり、修正される予定です。Joseph S. Myers の投稿で述べられている意図は、予測可能にすることです。
Clang が過剰な精度を処理する方法 (オプション-mno-sse2
を使用する場合など) は文書化されていますか?
(*) 編集: これは誇張です。x87 FPU を 53 ビット仮数を使用するように構成できる場合、binary64 をエミュレートするのは少し面倒ですが、それほど難しくありません。
以下のR..によるコメントに続いて、これは私が持っている最新バージョンのClangとの私の短い相互作用のログです:
assembly - 32 マシンで 32 ビットの数値を加算し、2 つのレジスタで 64 ビットの合計に拡張する
32 ビット マシンで精度を落とさずに、つまり 64 ビットの「疑似レジスタ」で 2 つの 32 ビット数値を追加する方法eax:edx
。Intel 構文アセンブラを使用します。
c++ - C++ での無相関例外処理に依存する浮動小数点 NaN
本当に奇妙です:
いくつかの最適化により、2 番目の c の結果が 0 になる可能性があります。
BUT : try/catch ブロックを削除すると、2 番目の c は NaN のままです! なぜこの異なる動作??? 私のコンパイラは VC++ 2010 Express です。OS Windows7 64ビット。iostream や cmath などの標準ライブラリのみを使用します。
編集:私の最初の観察は、空のコンソールアプリケーションのDebug + Win32デフォルト設定でした。Release+Win32 では、結果は次のとおりです。最初の c 0、2 番目の c NaN - try/catch が存在するかどうかに関係なく! 概要:
編集 2 : /fp:strict
C++/コード生成でスイッチを設定すると、結果は Debug+Win32 と同じですが、Release+Win32 では、try の有無に関係なく、c = a * b; // NaN
に変わります。Debug+Win32 のc = (1/sigma) * exp(-1/sigma); // 0
ままで、先行試行がない理由がわかりません。前の試行に応じてNaN+NaN
結果がリリースと異なる場合、浮動小数点セーフでなければならないプログラムをデバッグする方法は?/fp:strict
編集3:ここに完全なプログラムがあります:
assembly - 巨大な数に対する最速のx86-64アセンブリ言語除算アルゴリズムは何ですか?
s0128
x86-64 アセンブリ言語でコード ライブラリを作成して、 、s0256
、s0512
、s1024
符号付き整数型およびf0128
、f0256
、f0512
、f1024
浮動小数点型のすべての従来のビット単位、シフト、論理、比較、算術、および数学関数を提供しています。浮動小数点関数は、整数型用に作成された内部ルーチンを呼び出す可能性が高いため、ここまでは符号付き整数型に取り組んでいます。
これまで、さまざまな単項演算子、比較演算子、および加算、減算、乗算の各演算子を実行する関数を作成してテストしてきました。
現在、除算演算子の関数を実装する方法を決定しようとしています。
私の最初の考えは、「ニュートン・ラフソンが最善のアプローチに違いない」というものでした。なんで?適切なシード (最初の推測) が与えられると非常に迅速に収束するため、オペランドでネイティブの 64 ビット除算命令を実行して優れたシード値を取得する方法を理解できるはずです。実際、シード値が 64 ビットまで正確である場合、正しい答えを得るには次のようにする必要があります。
しかし、この質問についてもう少し考えてみると、私は疑問に思います。たとえば、すべての大きな整数型に対して乗算演算を実行する、私が書いたコア ルーチンを思い出します。
ループがかなり短く効率的 (キャッシュを含む) であるにもかかわらず、より広いデータ型の操作の増加はかなりのものです。このループは、結果の各 64 ビット部分を 1 回だけ書き込み、その後の処理のために結果のどの部分も読み戻すことはありません。
これにより、特に大きな型の場合、従来のシフトと減算型の除算アルゴリズムの方が高速になるのではないかと考えるようになりました。
私の最初の考えはこれでした:
#1: 各ビットを計算するには、通常、除数が被除数以下の場合、被除数から除数を減算します。通常、最も重要な 64 ビット部分を検査するだけで、除数が被除数より確実に小さいか、または大きいかを判断できます。これらの ms64 ビット部分が等しい場合にのみ、ルーチンは次の下位 64 ビット部分をチェックする必要があり、それらが等しい場合にのみさらに下位をチェックする必要があります。したがって、ほぼすべての反復 (結果の各ビットを計算する) で、このテストを計算するために実行される命令を大幅に減らすことができます。
#2:しかし...平均して、約50%の確率で、被除数から除数を引く必要があることがわかります。とにかく、幅全体を引く必要があります。この場合、実際には従来のアプローチよりも多くの命令を実行しました (最初にそれらを減算し、次にフラグをテストして除数 <= 被除数かどうかを判断します)。したがって、半分の時間は節約を実現し、半分の時間は損失を実現します。s1024
(16 ~ 64 ビットのコンポーネントを含む) のような大きな型では、大幅な節約と損失が小さいため、このアプローチは大幅な正味の節約を実現するはずです。(-2- 64 ビット コンポーネントを含む) のような小さな型s0128
では、節約はわずかであり、大きな損失ではありませんが、大きなものではありません。
したがって、私の質問は、「最も効率的な除算アルゴリズムは何ですか」ということです。
注: 私の推測では、実際の実装は符号なし整数でのみ動作します。乗算の場合、負のオペランドを正に変換してから符号なし乗算を実行し、元のオペランドが 1 つでも負であれば結果を否定する方が簡単で効率的であることが (おそらく) 判明しました。ただし、効率的である場合は、符号付き整数アルゴリズムを検討します。
注: 浮動小数点型 ( f0128
、f0256
、f0512
、f1024
) の最良の答えが異なる場合は、その理由を説明してください。
注: これらすべての整数データ型に対して乗算演算を実行する内部コアの unsigned-multiply ルーチンは、倍幅の結果を生成します。言い換えると:
私のコード ライブラリには、符号付き整数データ型ごとに 2 つのバージョンの乗算が用意されています。
これは、「精度を失わない」および「オーバーフローしない」という私のコード ライブラリのポリシーと一致しています (精度の低下またはオーバーフロー/アンダーフローが原因で回答が無効な場合、エラーが返されます)。ただし、倍幅の戻り値関数が呼び出された場合、そのようなエラーは発生しません。
gcc - __int128 組み込み型をサポートする gcc のバージョンはどれですか?
gcc docsの下で128 ビット整数は次のとおりです。
拡張機能として、整数スカラー型
__int128
は、128 ビットを保持するのに十分な幅の整数モードを持つターゲットに対してサポートされています。__int128
符号付き 128ビット整数、または符号なし 128 ビット整数を単に記述しunsigned __int128
ます。
__int128
GCC では、128 ビット幅未満の long long integer を持つターゲットのタイプの整数定数を表現するためのサポートはありません。
このタイプのサポートを追加した gcc のバージョンは何か、またはその存在をテストするために直接使用できるマクロがあるかどうか疑問に思っていました。
fortran - 非常に大きな実数での精度の問題 - Fortran
私が現在取り組もうとしている問題は、10 modulo(n) の次数を計算することです。ここで、n は 1000 未満の任意の数である可能性があります。正確にそれを行う関数がありますが、正確な結果を得ることができません。注文の価値が上がるにつれて。
この関数は、注文が十分に小さい限り正しく機能しますが、注文が多い場合は正しくない値を返します。そのため、問題を特定するために端末への出力をいくつか残しておき、累乗を使用すると実数の精度が損なわれることを発見しました。
関数ですべての変数を宣言し、プログラムで実際の(kind = nkind)としてテストしました。ここで、nkind = selected_real_kind(p = 18、r = 308)です。明示的に参照される数値は、たとえば 1.0_nkind としても宣言されます。ただし、1 から数えて n に対して 10**n を出力すると、10**27 で値が正しいことがわかります。ただし、10**28 は 9999999999999999999731564544 を返します。すべての高べき乗は同様に歪んでおり、この不正確さが問題の原因です。
それで、私の質問は、エラーを回避する方法はありますか? 計算で既に使用しているよりも拡張された精度を使用する方法がわかりません。
ありがとう、ショーン
*編集: コードで見ることはあまりありませんが、ここに行きます: