10

私が解釈すると、MSDN の定義numeric_limits::is_exactほとんどの場合誤りです。

[this] 型で実行される [all] 計算には、丸め誤差がありません。

そして、IBM の定義はほぼ常に真です: (または、読み方によっては循環的な定義です)

すべての値の正確な表現を持つ型

私が確信しているのは、 aと a の2両方に aを格納でき、両方とも正確に表現されるということです。 doublelong

次に、それらを両方で割ることができますが10、どちらも数学的な結果を正確に保持しません。

数値データ型が与えられた場合T、定義する正しい方法は何std::numeric_limits<T>::is_exactですか?

編集:多くの回答で提供された詳細から、この質問 に対する正確な回答だと思うものを投稿しました。この回答は、報奨金の候補ではありません

4

6 に答える 6

7

標準の定義 (NPE の回答を参照) はあまり正確ではありませんね。代わりに、それは循環的で曖昧です。

IEC 浮動小数点標準には「不正確な」数の概念 (および計算によって不正確な数が得られる場合の不正確な例外) があることを考えると、これが名前の由来であると思われis_exactます。標準タイプのうち、は、、およびis_exactに対してのみ false であることに注意してください。floatdoublelong double

その意図は、型が基礎となる数学的型のすべての数値を正確に表しているかどうかを示すことです。整数型の場合、基礎となる数学的型は整数の有限サブセットです。各整数型は、その型の対象となる整数のサブセットのメンバーのすべてを正確に表すため、is_exactすべての整数型に当てはまります。浮動小数点型の場合、基礎となる数学型は、実数の有限範囲サブセットです。(有限範囲サブセットの例は、「0 と 1 の間のすべての実数」です。) 実数の有限範囲サブセットでさえ正確に表す方法はありません。ほとんどすべてが計算不能です。IEC/IEEE 形式では、事態はさらに悪化します。その形式では、コンピューターは有理数の有限範囲サブセットを正確に表すことさえできません (計算可能な数の有限範囲サブセットは言うまでもなく)。

is_exactこの用語の起源は、さまざまな浮動小数点表現モデルにおける「不正確な」数の長年の概念であると思われます。おそらくもっと良い名前だったでしょうis_complete

補遺
言語によって定義された数値型は、「数値」の表現のすべてではありません。固定小数点表現は本質的に整数であるため、それらも正確です (表現に穴はありません)。有理数を標準的な整数型 (たとえばint/int) のペアとして表現することは正確ではありませんが、有理数をBignumペアとして表現するクラスは、少なくとも理論的には「正確」になります。

実物はどうですか?ほとんどすべての実数が計算可能ではないため、実数を正確に表す方法はありません。私たちがコンピューターでできる最善のことは、計算可能な数値です。それには、数値を何らかのアルゴリズムとして表す必要があります。これは理論的には役立つかもしれませんが、実用的な観点からは、まったく役に立ちません。

2 番目の補遺
開始する場所は、標準です。C++03 と C++11 はどちらも次is_exactのように定義します。

型が正確な表現を使用する場合は true。

それはあいまいであり、循環的でもあります。無意味です。char整数型 ( 、shortintlongなど) が fiat によって「正確」であることはそれほど無意味ではありません。

すべての整数型は正確です...

他の算術型はどうですか?最初に注意すべきことは、他の算術型は浮動小数点型floatdouble、およびlong double(3.9.1/8) のみであるということです。

floatdouble、およびの 3 つの浮動小数点型がありlong doubleます。... 浮動小数点型の値表現は実装定義です。整数型と浮動小数点型をまとめて算術型と呼びます。

C++ における浮動小数点型の意味は、非常にあいまいです。Fortran と比較します。

実数データは、実数の値に対するプロセッサの近似値です。

ISO/IEC 10967-1、言語に依存しない算術演算 (C++ 標準では脚注で参照されていますが、規範的な参照としては決して参照されていません) と比較してください。

浮動小数点型Fは、ℝ の有限部分集合でなければなりません。

一方、C++ は、浮動小数点型が何を表すと想定されているかに関しては議論の余地があります。私が知る限り、実装はのシノニム、のシノニム、のfloatシノニムを作成することでうまくいく可能性があります。intdoublelonglong doublelong long

上の標準からもう一度is_exact:

...しかし、すべての正確な型が整数であるとは限りません。たとえば、有理数と固定指数の表現は正確ですが、整数ではありません。

これは明らかに、ユーザーが定義することを許可されていないという単純な理由から、ユーザーが開発した拡張には適用されませんstd::whatever<MyType>。それを行うと、未定義の動作が呼び出されます。この最後の節は、次の実装にのみ関係します。

  • floatdouble、およびを特定の方法で定義するlong doubleか、または
  • std::numeric_limits<non_standard_type>非標準の有理数型または固定小数点型を算術型として提供し、これらの非標準拡張に を提供することを決定します。
于 2013-01-07T22:41:38.790 に答える
5

その型のすべてのリテラルが正確な値を持っている場合、 is_exact が真であることをお勧めします。したがって、リテラル 0.1 の値は正確に 0.1 ではないため、浮動型の is_exact は false です。

Christian Rau のコメントによると、型の任意の 2 つの値の間の 4 つの算術演算の結果が範囲外であるか、その型の演算の定義を使用して正確に表すことができる場合、代わりに is_exact を true と定義できます (つまり、 、整数除算の切り捨て、符号なしラップアラウンド)。この定義を使用すると、浮動小数点演算が最も近い表現可能な値を生成するように定義されていることを気にすることができます。しないでください:-)

于 2013-01-08T15:55:44.073 に答える
3

正確さの問題はCに限定されないので、さらに調べてみましょう。

標準の編集についてのドイツ語の議論は別として、不正確さは、同じタイプで結果を表すために丸めを必要とする数学演算に適用する必要があります。たとえば、Schemeには、正確な演算と正確なリテラル定数による正確性/不正確性のそのような定義があります。R5RS§6を参照してください。http://www.schemers.org/Documents/Standards/R5RS/HTMLの標準手順

0.1は明確に定義された二重リテラルであると見なすか、Schemeの場合double x=0.1のように、リテラルは不正確なコンパイル時操作によって形成された不正確な定数であると見なします(操作1/10の結果を最も近い2倍に丸めます。 Qで定義)。ですから、私たちは常に運用に行き着きます。

+に集中しましょう。他は、+とグループプロパティによって数学的に定義できます。

その場合、不正確さの考えられる定義は次のようになります。

If there exists any pair of values (a,b) of a type such that a+b-a-b != 0,
then this type is inexact (in the sense that + operation is inexact).

私たちが知っているすべての浮動小数点表現(nanとinfが離れている自明な場合)には、明らかにそのようなペアが存在するため、float(演算)が不正確であることがわかります。

明確に定義された符号なし算術モデルの場合、+は正確です。

signed intの場合、オーバーフローが発生した場合のUBの問題があるため、正確性の保証はありません...この壊れた算術モデルに対処するためにルールを改良しない限り、次のようになります。

If there exists any pair (a,b) such that (a+b) is well defined
and a+b-a-b != 0,
then the + operation is inexact.

上記の明確な定義は、他の操作にも拡張するのに役立ちますが、実際には必要ありません。
次に、/の場合を不正確ではなく誤ったポリモーフィズムと見なす必要があります
(/はintの除法の原理の商として定義されます)。

もちろん、これは公式のルールではありません。この回答の有効性は合理的な思考の努力に限定されています

于 2013-01-10T23:37:55.717 に答える
2
于 2013-01-11T02:36:38.073 に答える
2

C++ 標準で与えられた定義はかなり明確に見えます。

static constexpr bool is_exact;

型が正確な表現を使用する場合は true。すべての整数型は正確ですが、すべての正確な型が整数というわけではありません。たとえば、有理数と固定指数の表現は正確ですが、整数ではありません。

すべての専門分野に意味があります。

于 2013-01-07T20:40:28.927 に答える
2

std::numeric_limits<T>::is_exactの定義が格納できない可能性のある値を許可するfalse場合にのみ、 であるべきです。T

C++ は、浮動小数点リテラルをその型の有効な値と見なします。また、実装は、どの値が正確に格納された表現を持つかを決定することができます。

2.0そのため、許可された範囲 (やなど) 内の実数ごとに0.2、C++はその数値が有効であることを常に約束し、値が正確に格納できることを決して約束しません。double

これは、質問で行われた 2 つの仮定が、ユビキタスなIEEE 浮動小数点標準には当てはまりますが、C++ 定義には正しくないことを意味します。

2aを正確に double に格納できると確信しています。

次に、[それ] を で割る10と、[倍精度ではない] 数学的な結果が正確に保持されます。

于 2013-01-12T20:18:10.857 に答える