日々の記録。

プログラミングのメモや感じた事などを記録。

C++講座 その4 整数型と浮動小数点

整数型

C言語と同様にintが整数型.よく利用するshortやlongという型はshort int, long intの省略形。

整数リテラル

3
-5
12352
0x53

といった値が整数リテラル。上記の値はintとして扱われる。 サイズを意識しなくて良い場合、整数値にはint型を利用した方が良い。

整数型の注意1 除算

整数値を除算すると、小数点は切り捨てられ最も近い整数値になるので注意。除算を行うには浮動小数点を用いること。

整数型の注意2 桁あふれ

int が32bitの場合、表現できる値は-2,147,483,648~2147,483,647まで。例えばINTの最大値に1を加算すると次のようになる。

int n = 0x7FFFFFFF // (2147,483,647)
n++; // 0x80000000 (-2147483648)

浮動小数点型

C言語と同様にfloat, double, (long double)が浮動小数点型。

浮動小数点は誤差が発生するため、計算方法や比較方法に注意すること。 (業務では、浮動小数点を使った数値演算とはあまり行わないので、以下の記述は誤っているかもしれない。)

注意1 浮動小数点で、同値比較に f1 == f2 はNG

double a = 0.1;
double b = 0.2;
double c = a + b;
if( c == 0.3 ) {
// ok!!
} else {
// ng!!
}

一見(a + b) = 0.3のように見えるが、誤差によりngの処理に入る。 この場合、次のような解決方法がある。

この例は小数(浮動小数点数型)の計算が思った結果にならない理由と解決法を参考。理由等もこちらに記載されている。

解決策1 abs(a - b) <= DELTA

== で比較するのではなく、aとbの差が許容値(DELTA)以内なら等しいと見なす。

const int DELTA = 0.0001
if( fabs(c - 0.3) <= DELTA ) {
  cout << "equal!!" << endl;
} else {
  cout << c << " not equal!!" << endl;
}

このDELTAには計算機イプシロンよりも大きな値を設定する必要がある。尚、C/C++では計算機イプシロン用の定数が用意されている。 計算機イプシロン(wikipedia)

解決策2 10の倍数をかけて整数にする

現在勤めている会社では、こちらの方を利用する方が多い。(とりうる値の範囲が明確で、整数型に収まる場合には有効だから?)

int ia = static_cast<int>(round(a * 10));
int ib = static_cast<int>(round(b * 10));
int ic = a + b;
if( ic == 3 ) {
  cout << "equal!!" << endl;
} else {
  cout << c << " not equal!!" << endl;
}

注意2 大きさが極端に異なる数の加算や減算は行わない。

演算結果に誤差が発生する可能性がある。 このような場合、絶対値の小さい順にソートを行ってから、演算することで誤差を減らせる。

注意3 他OSなど異なる環境に浮動小数点を渡す場合は、浮動小数点の扱いに注意すること

他環境が同じ仕様の浮動小数点を扱っているとは限らないので、浮動小数点以外の値(整数値やBCDなど)に 変換する事も考慮する。

まとめ

などと浮動小数点を利用する場合には注意すること。