構文のあるfloor
関数が欲しいのですが
int floor(double x);
だが std::floor
はdouble
を返します。です
static_cast <int> (std::floor(x));
正しい整数が得られることが保証されていますか、それとも1つずつ問題が発生する可能性がありますか?うまくいくようですが、確実に知りたいです。
ボーナスポイントについては、なぜ一体何をするのかstd::floor
そもそもdouble
を返しますか?
Doubleの範囲は、32ビットまたは64ビット整数の範囲よりもはるかに大きいため、std::floor
はdouble
を返します。 int
へのキャストは、適切な範囲内であれば問題ありませんが、double
はすべての64ビット整数を正確に表すことができないため、エラーが発生する可能性があることに注意してください。 double
の精度が、2つの連続するdoubleの差が1より大きくなるポイントを超えています。
static_cast <int> (std::floor(x));
はい、あなたが望むことをほぼ実行します。これは、-無限大に向かって丸められた最も近い整数を提供します。少なくとも、入力がintで表現できる範囲内にある限り。 '.5などを追加するとどういう意味かわかりませんが、同じ効果はありません
そして、std :: floorは、それが最も一般的であるため、doubleを返します。場合によっては、floatまたはdoubleを四捨五入したいが、型は保持したい場合があります。つまり、1ではなく1.3fを1.0fに丸めます。
Std :: floorがintを返した場合、それを行うのは難しいでしょう。 (または少なくとも、そこに余分な不要なキャストがあり、物事が遅くなります)。
フロアがタイプを変更せずに丸め自体のみを実行する場合は、必要に応じて、それを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バージョンも提供します。 std :: floorf()は、doubleを使用したくない場合のstd :: floor()の単精度バージョンです。
編集:以前の回答の一部を削除しました。 intにキャストするときにフロアが冗長であると述べましたが、これは正の浮動小数点数にのみ当てはまるということを忘れていました。