floor
構文の関数が欲しい
int floor(double x);
しかし、std::floor
を返しますdouble
。は
static_cast <int> (std::floor(x));
私に正しい整数を与えることが保証されていますか、それともオフバイワンの問題が発生する可能性がありますか? うまくいくようですが、確実に知りたいです。
ボーナス ポイントの場合、一体なぜそもそもa がstd::floor
返されるのでしょうか。double
double の範囲は、32 ビットまたは 64 ビット整数の範囲よりもはるかに大きいため、 a がstd::floor
返されますdouble
。へのキャストint
は、それが適切な範囲内にある限り問題ないはずですが、 adouble
はすべての 64 ビット整数を正確に表すことはできないdouble
ことに注意してください。連続する 2 つの double の差が 1 より大きいこと。
static_cast <int> (std::floor(x));
はい、ほとんどあなたが望むことをします。-infinity に向かって丸められた、最も近い整数が得られます。少なくとも、入力が int で表現できる範囲内にある限り。「.5 などを追加する」とはどういう意味かわかりませんが、同じ効果はありません。
std::floor は double を返します。これが最も一般的なためです。float または double を四捨五入したいが、型を保持したい場合があります。つまり、1.3f を 1 ではなく 1.0f に丸めます。
std::floor が int を返した場合、それは難しいでしょう。(または、少なくとも余分な不要なキャストがあり、速度が低下します)。
floor が型を変更せずに丸めのみを実行する場合は、必要に応じてそれを int にキャストできます。
もう 1 つの理由は、double の範囲が int の範囲よりもはるかに大きいことです。すべての double を int に丸めることができない場合があります。
C++ 標準は次のように述べています (4.9.1):
「浮動小数点型の右辺値は、整数型の右辺値に変換できます。変換は切り捨てられます。つまり、小数部分は破棄されます。切り捨てられた値が宛先の型で表現できない場合、動作は未定義です」.
したがって、double を int に変換する場合、数値が int の範囲内にあり、必要な切り上げがゼロに向かっている場合は、単純に数値を int にキャストするだけで十分です。
(int)x;
さまざまな数値条件を処理し、さまざまな種類の変換を制御された方法で処理したい場合は、Boost.NumericConversionを確認する必要があります。このライブラリを使用すると、奇妙なケース (範囲外、丸め、範囲など) を処理できます。
ドキュメントの例を次に示します。
#include <cassert>
#include <boost/numeric/conversion/converter.hpp>
int main() {
typedef boost::numeric::converter<int,double> Double2Int ;
int x = Double2Int::convert(2.0);
assert ( x == 2 );
int y = Double2Int()(3.14); // As a function object.
assert ( y == 3 ) ; // The default rounding is trunc.
try
{
double m = boost::numeric::bounds<double>::highest();
int z = Double2Int::convert(m); // By default throws positive_overflow()
}
catch ( boost::numeric::positive_overflow const& )
{
}
return 0;
}
標準数学ライブラリのほとんどは double を使用しますが、float バージョンも提供します。double を使用したくない場合、std::floorf() は std::floor() の単精度バージョンです。
編集:以前の回答の一部を削除しました。int にキャストする場合、フロアは冗長であると述べましたが、これは正の浮動小数点数にのみ当てはまることを忘れていました。