3

特定のコンピューターで仮数桁数と単位の丸めを見つけたいと思っています。これらが何であるかは理解していますが、それらを見つける方法がわかりません-ただし、コンピューターによって異なる場合があることは理解しています.

エラーの分析など、数値解析の特定の側面を実行するには、この数値が必要です。

私が現在考えているのは、オーバーフローが発生するまで数値をゆっくりとインクリメントする小さな C++ プログラムを作成できるということですが、どのタイプの数値を使用すればよいかわかりません。

私は正しい軌道に乗っていますか?これを正確に計算するにはどうすればよいでしょうか。

4

3 に答える 3

5

使用している言語が何であれ、フロートの格納方法を指定すると思います。Javaが特定のIEEE標準(754だと思います)を使用してこれを行うことは知っています。

指定されていない場合は、0.5 に 1 を追加して、実際の数値が変化するかどうかを確認するだけで、独自のチェックを行うことができると思います。そうであれば、0.25 を 1 に、0.125 を 1 に、というように数値が変化しなくなるまで追加します。次のようになります。

float a = 1;
float b = 0.5;
int bits = 0;
while (a + b != a) {
    bits = bits + 1;
    b = b / 2;
}

仮数ビットが 3 ビットしかない場合、1 + 1/16 は 1 になります。

次に、仮数ビットを使い果たしました。

IEEE754 は最初に暗黙の '1+' を使用するため、基数を 1 ではなく 2 にする必要があるかもしれません。

編集:

上記の方法には、明らかに 4 バイトの浮動小数点があるシステムに 63 ビットが与えられるため、いくつかの問題があるようです。

それが中間結果に関係しているかどうか(明示的なキャスト [ while (((float)(a + b) != (float)(a))] を使用した同じコードには同様の問題があるため、疑わしい)または(より可能性が高いと思います)単位値を調整することによりa、小数に近いビットで表現できる可能性があります。b指数、まだわかりません。

今のところ、IEEE754 の使用など、上記の言語情報に依存するのが最善です (その情報が利用可能な場合)。

問題のあるコードは、用心深いプレイヤーの罠として残しておきます。たぶん、浮動小数点の知識が豊富な人なら、それが奇妙に動作する理由を説明するメモを残すことができます (推測はしないでください:-)。

編集2:

このコードは、中間体が float に格納されるようにすることで問題を修正します。Jonathan Leffler が正しかったことが判明しました - それは中間結果でした。

#include <stdio.h>
#include <float.h>

int main(void) {
    float a = 1;
    float b = 0.5;
    float c = a + b;
    int bits = 1;
    while (c != a) {
        bits = bits + 1;
        b = b / 2;
        c = a + b;
    }
    printf("%d\n",FLT_MANT_DIG);
    printf("%d\n",bits);
    return 0;

}

このコードは (24,24) を出力して、計算された値がヘッダー ファイルの値と一致することを示します。

C で書かれていますが、どの言語にも適用できるはずです (特に、情報がヘッダーで利用できない場合、または言語ドキュメントで指定されているため)。私のUbuntuボックスではEclipseの起動に時間がかかるため、Cでのみテストしました:-)。

于 2009-02-02T02:31:47.980 に答える
1

<limits>C++ ライブラリでチェックアウトすることをお勧めします。

#include <iostream>
#include <limits>
#include <typeinfo>

template <typename T>
void printDetailsFor() {
    std::cout
        << "Printing details for " << typeid(T).name() << ":\n"
        << "\tradix:        " << std::numeric_limits<T>::radix        << "\n"
        << "\tradix digits: " << std::numeric_limits<T>::digits       << "\n"
        << "\tepsilon:      " << std::numeric_limits<T>::epsilon()    << "\n"
        << std::endl;
}

int main() {
    printDetailsFor<int>();
    printDetailsFor<float>();
    printDetailsFor<double>();
    printDetailsFor<long double>();
    return 0;
}

std::numeric_limits<T>::digitsどちらが仮数ビット数よりも 1 多いかが必要だと思います。私のマシンは次のように出力します:

Printing details for i:
    radix:        2
    radix digits: 31
    epsilon:      0

Printing details for f:
    radix:        2
    radix digits: 24
    epsilon:      1.19209e-07

Printing details for d:
    radix:        2
    radix digits: 53
    epsilon:      2.22045e-16

Printing details for e:
    radix:        2
    radix digits: 64
    epsilon:      1.0842e-19
于 2009-02-02T03:35:33.967 に答える
1

C の場合、および拡張 C++ の場合、情報は<float.h>または<cfloat>ヘッダーにあります。

C99 の場合、情報は標準のセクション 5.2.4.2.2 にあります。

  • FLT_RADIX
  • FLT_MANT_DIG
  • FLT_DIG
  • FLT_EPSILON
  • FLT_MIN_EXP
  • FLT_MIN
  • FLT_MIN_10_EXP
  • FLT_MAX_EXP
  • FLT_MAX
  • FLT_MAX_10_EXP

同様に、これらのほとんどの DBL および LDBL バリエーションについても (noDBL_RADIXまたはLDBL_RADIX)。この規格は、IEEE 754 に適した値を提案しています (IEEE 754 規格の古いバージョンは 1999 年時点のもので、新しいバージョンは 2008 年に公開されたと思います)。

于 2009-02-02T02:49:51.877 に答える