static_cast
例えば以下のようなコードがあるとする。
#include <iostream>
int main(void)
{
float a = 2.9;
std::cout << "a: " << static_cast<int>(a) << std::endl;
return 0;
}
結果
a: 2
2.9
がint 2
にキャストされ、0.9
の誤差が生じることになる。
それはまずいので明示的に 切り上げ/切り捨て/四捨五入 をC++標準ライブラリを用いて行う。
std::ceil (切り上げ)
#include <iostream>
#include <cmath> // これが必要
int main(void)
{
float a = 2.9;
std::cout << "a: " << std::ceil(a) << std::endl;
return 0;
}
結果
3
これで3に切り上げができたが、問題がある。
2.1を切り上げるとどうなるだろうか見てみよう。
#include <iostream>
#include <cmath> // これが必要
int main(void)
{
float a = 2.1;
std::cout << "a: " << std::ceil(a) << std::endl;
return 0;
}
結果
3
また誤差が0.9
ある。
std::floor (負の方向に切り捨て)
#include <iostream>
#include <cmath> // これが必要
int main(void)
{
float a = 2.1;
std::cout << "a: " << std::floor(a) << std::endl;
return 0;
}
結果
2
これで2に切り捨てができたが、static_castと明確に違う点がある。
それは、std::floorは常に負の方向に切り捨てを行う。
static_castは常に0に向かって切り捨てを行う。
static_castの場合、
float a = 2.5;
float b = -2.5;
std::cout << "a: " << static_cast<int>(a) << std::endl;
std::cout << "b: " << static_cast<int>(b) << std::endl;
結果
a: 2
b: -2
となるが
std::floorの場合、
float a = 2.5;
float b = -2.5;
std::cout << "a: " << std::floor(a) << std::endl;
std::cout << "b: " << std::floor(b) << std::endl;
結果
a: 2
b: -3
常に負の方向に切り捨てされることに注意して使う必要がある。
std::trunc (0の方向に切り捨て)
実は常に0の方向に切り捨てを明示的に行える。
#include <iostream>
#include <cmath> // これが必要
int main(void)
{
float a = 2.5;
float b = -2.5;
std::cout << "a: " << std::trunc(a) << std::endl;
std::cout << "b: " << std::trunc(b) << std::endl;
return 0;
}
結果
a: 2
b: -2
static_castとの違いは後ほど。
std::round (四捨五入)
いよいよ四捨五入です。
#include <iostream>
#include <cmath> // これが必要
int main(void)
{
float a = 2.4;
float b = 2.5;
std::cout << "a: " << std::round(a) << std::endl;
std::cout << "b: " << std::round(b) << std::endl;
return 0;
}
結果
a: 2
b: 3
ぶっちゃけこいつが一番使うと思います。
-2.4
を渡すと-2
に、-2.5
を渡すと-3
が得られます。
static_castと明確な違い
static_castはキャスト(型変換)を行っているので、float型からint型に変換されています。
しかし、上で説明した 切り上げ/切り捨て/四捨五入 は型変換を行っていません。
なのでいくらfloat a = 2.5
をstd::round
で3
にしようと3.0
となっているだけです。
ここはしっかりと理解した上で使う必要があります。