1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【C++】数値の明示的な切り上げ/切り捨て/四捨五入

Last updated at Posted at 2024-10-28

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.9int 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.5std::round3にしようと3.0となっているだけです。
ここはしっかりと理解した上で使う必要があります。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?