C++では、浮動小数点値(float)を fixed point (int、16:16)に変換する一般的な方法は何ですか?または24:8)?
EDIT:明確にするために、固定小数点値には、整数部分と小数部分の2つの部分があります。整数部分は、符号付きまたは符号なし整数データ型で表すことができます。小数部は、符号なしデータ整数データ型で表されます。
わかりやすくするために、お金で例えましょう。小数部分はセントを表す場合があります-ドルの小数部分。 'cents'データ型の範囲は0〜99です。固定小数点演算に8ビットの符号なし整数を使用する場合、小数部は256の割り切れる整数部に分割されます。
それで問題が解決することを願っています。
どうぞ:
// 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)
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);
****編集**:私の最初のコメントはケビンの編集前に適用されますが、後世のためにここに残しておきます。答えはここですぐに変わることがあります!
Kevinのアプローチの問題は、Fixed Pointを使用すると、通常、保証されたワードサイズ(通常は32ビット)にパックされることです。 2つの部分を別々に宣言すると、コンパイラの構造パッキングの気まぐれになります。はい、強制することはできますが、16:16の表現以外では機能しません。
KPexEAは、すべてをintにパックすることで、マークに近づきます。ただし、「signed long」を使用して、32ビットで明示的にしようとします。次に、彼のアプローチを使用して固定小数点値を生成できます。ビットスライスでは、コンポーネントパーツが再度抽出されます。彼の提案は24:8のケースもカバーしています。
(そしてstatic_castだけを提案した他のみんな.....あなたは何を考えていましたか?;))
私はベストアンサーを書いた人に答えを出しましたが、私は実際に ここ を指す関連する質問コードを使用しました。
テンプレートを使用し、ブーストライブラリへの依存関係を簡単に捨てることができました。
これは浮動小数点から整数への変換には問題ありませんが、O.P。も 固定小数点 を望んでいました。
さて、C++でそれをどのように行うかはわかりません(C++は私がすぐに考えることができるものではありません)。おそらく、スケーリングされた整数のアプローチを試してください。つまり、32ビットまたは64ビットの整数を使用し、プログラムで最後の6桁を小数点の右側に割り当てます。