web-dev-qa-db-ja.com

浮動小数点を固定小数点に変換する

C++では、浮動小数点値(float)を fixed point (int、16:16)に変換する一般的な方法は何ですか?または24:8)?

EDIT:明確にするために、固定小数点値には、整数部分と小数部分の2つの部分があります。整数部分は、符号付きまたは符号なし整数データ型で表すことができます。小数部は、符号なしデータ整数データ型で表されます。

わかりやすくするために、お金で例えましょう。小数部分はセントを表す場合があります-ドルの小数部分。 'cents'データ型の範囲は0〜99です。固定小数点演算に8ビットの符号なし整数を使用する場合、小数部は256の割り切れる整数部に分割されます。

それで問題が解決することを願っています。

21
CVertex

どうぞ:

// A signed fixed-point 16:16 class
class FixedPoint_16_16
{
    short          intPart;
    unsigned short fracPart;

public:
    FixedPoint_16_16(double d)
    {
        *this = d; // calls operator=
    }

    FixedPoint_16_16& operator=(double d)
    {
        intPart = static_cast<short>(d);
        fracPart = static_cast<unsigned short>
                    (numeric_limits<unsigned short> + 1.0)*d);
        return *this;
    }

    // Other operators can be defined here
};

EDIT:これは、固定小数点数を処理する別の一般的な方法に基づく、より一般的なクラスです(KPexEAが指摘しました)。

template <class BaseType, size_t FracDigits>
class fixed_point
{
    const static BaseType factor = 1 << FracDigits;

    BaseType data;

public:
    fixed_point(double d)
    {
        *this = d; // calls operator=
    }

    fixed_point& operator=(double d)
    {
        data = static_cast<BaseType>(d*factor);
        return *this;
    }

    BaseType raw_data() const
    {
        return data;
    }

    // Other operators can be defined here
};


fixed_point<int, 8> fp1;           // Will be signed 24:8 (if int is 32-bits)
fixed_point<unsigned int, 16> fp1; // Will be unsigned 16:16 (if int is 32-bits)
28
Kevin

Floatからintegerへのキャストでは、小数部分が破棄されるため、その小数を固定小数点として保持したい場合は、キャストする前に浮動小数点を乗算するだけです。以下のコードはオーバーフローをチェックしません。

16:16が必要な場合

double f = 1.2345;
int n;

n=(int)(f*65536);

24:8が必要な場合

double f = 1.2345;
int n;

n=(int)(f*256);
21
KPexEA

****編集**:私の最初のコメントはケビンの編集前に適用されますが、後世のためにここに残しておきます。答えはここですぐに変わることがあります!

Kevinのアプローチの問題は、Fixed Pointを使用すると、通常、保証されたワードサイズ(通常は32ビット)にパックされることです。 2つの部分を別々に宣言すると、コンパイラの構造パッキングの気まぐれになります。はい、強制することはできますが、16:16の表現以外では機能しません。

KPexEAは、すべてをintにパックすることで、マークに近づきます。ただし、「signed long」を使用して、32ビットで明示的にしようとします。次に、彼のアプローチを使用して固定小数点値を生成できます。ビットスライスでは、コンポーネントパーツが再度抽出されます。彼の提案は24:8のケースもカバーしています。

(そしてstatic_castだけを提案した他のみんな.....あなたは何を考えていましたか?;))

7
Greg Whitfield

私はベストアンサーを書いた人に答えを出しましたが、私は実際に ここ を指す関連する質問コードを使用しました。

テンプレートを使用し、ブーストライブラリへの依存関係を簡単に捨てることができました。

1
CVertex

これは浮動小数点から整数への変換には問題ありませんが、O.P。も 固定小数点 を望んでいました。

さて、C++でそれをどのように行うかはわかりません(C++は私がすぐに考えることができるものではありません)。おそらく、スケーリングされた整数のアプローチを試してください。つまり、32ビットまたは64ビットの整数を使用し、プログラムで最後の6桁を小数点の右側に割り当てます。

0
bugmagnet