C/C++でfloatとdoubleを比較する最も効果的な方法とは?
この記事では、C言語やC++で2つのfloat型またはdouble型の浮動小数点数を比較する方法について解説します。浮動小数点数の比較は、整数の比較とは性質が大きく異なるため、注意が必要です。
なぜ単純な等号比較ではいけないのか
浮動小数点数は内部で2進数として表現されるため、誤差が生じる可能性があります。そのため、==演算子による直接比較は期待どおりの結果にならないことがあります。正確に比較するには、「許容誤差(イプシロン)」を考慮に入れる必要があります。
例えば、3.1428と3.1415という2つの数値を考えてみましょう。精度0.01で見れば両者は同じ値とみなせますが、精度0.001で見ると異なる値になります。
比較の基本的な考え方
この基準に基づいて比較するには、次の手順を踏みます。
1. 片方の浮動小数点数からもう片方を引く
2. その結果の絶対値を求める
3. 絶対値が許容誤差(epsilon)より小さいかどうかを判定する
絶対値がイプシロン未満であれば、2つの値は「実質的に等しい」と判断できます。
サンプルコード
#include <iostream>
#include <cmath>
using namespace std;
// float型用の比較関数(デフォルトの許容誤差は0.01)
bool compare_float(float x, float y, float epsilon = 0.01f){
if(fabs(x - y) < epsilon)
return true; // 同じとみなせる
return false; // 同じではない
}
// double型用の比較関数(デフォルトの許容誤差は0.0000001)
bool compare_float(double x, double y, double epsilon = 0.0000001f){
if(fabs(x - y) < epsilon)
return true; // 同じとみなせる
return false; // 同じではない
}
int main() {
// float型の比較例
float x, y;
x = 22.0f/7.0f;
y = 3.1415f;
if(compare_float(x, y)){
cout << "They are equivalent" << endl;
} else {
cout << "They are not equivalent" << endl;
}
if(compare_float(x, y, 0.001f)){
cout << "They are equivalent" << endl;
} else {
cout << "They are not equivalent" << endl;
}
// double型の比較例
double a, b;
a = 2.03547415;
b = 2.03547428;
if(compare_float(a, b)){
cout << "They are equivalent" << endl;
} else {
cout << "They are not equivalent" << endl;
}
if(compare_float(a, b, 0.000001f)){
cout << "They are equivalent" << endl;
} else {
cout << "They are not equivalent" << endl;
}
}実行結果
They are equivalent They are not equivalent They are not equivalent They are equivalent
コードのポイント
このプログラムでは、関数オーバーロードを利用してfloat型とdouble型それぞれに対応した比較関数を定義しています。デフォルト引数として許容誤差を設定しておくことで、呼び出し側でイプシロンを省略することも、必要に応じて明示的に指定することも可能です。
22/7 ≒ 3.142857...と3.1415の差は約0.00135であるため、デフォルトの許容誤差0.01では「等価」と判定されますが、より厳しい0.001では「非等価」と判定されます。同様に、double型の例でも許容誤差の設定によって判定結果が変わることが確認できます。
このように、浮動小数点数を扱う際は常に誤差を意識し、目的に応じて適切なイプシロンを選択することが重要です。
-
C++で直方体の体積と表面積を計算するプログラムの作成方法
直方体とは? 直方体とは、6つの長方形の面から構成される三次元の立体図形です。各面の縦と横の長さが異なるため、全体として異なる長さの辺を持っています。立方体と直方体の違いは、立方体では長さ・高さ・幅がすべて等しいのに対し、直方体ではこれら3つが必ずしも同じではないという点です。 直方体の主な性質は以下のとおりです。 6つの面 12本の辺 8つの頂点 以下は直方体のイメージ図です。 問題の概要 直方体の長さ(L)、幅(W)、高さ(H)が与えられたとき、その総表面積と体積を求めるのが課題です。表面積とは各面が占める空間の広さのことであり、体積とはその形状が内包できる空間の大きさのことです。
-
サイファーパンクとは何者?その歴史と主張を徹底解説
暗号資産(仮想通貨)がニュースを賑わせる昨今、再び脚光を浴びているのが「サイファーパンク」と呼ばれるコミュニティです。ブロックチェーン技術の利用拡大に伴い、自らをサイファーパンクと称する人々は世界中で急速に増えており、政府や法執行機関にとっても無視できない存在となりつつあります。 では、サイファーパンクとは一体どんな人たちで、どこから来て、何を求めているのでしょうか。 サイファーパンクとは?その歴史 サイファーパンク運動には明確な「誕生日」はありませんが、その起源は1970年代半ばにさかのぼります。米国政府によるデータ暗号化標準(DES)の公表、そしてマーティン・ヘルマンとホイットフィールド・