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など)に 変換する事も考慮する。
まとめ
などと浮動小数点を利用する場合には注意すること。