基本的なことですが、、
値1と値2の差が誤差範囲内(例えば0.01)にあるか判定する場合
1.09
と
1.08
は誤差範囲内にあると認識したいところですが、
システム上のdoubleの値をとると、実際にはごみが入ります。
これの差分をとって0.01と比較すれば、値によって上回ったり下回ったりするかと思います。
どのように判定するのが正しいのでしょう。。
誤差の扱い
Re: 誤差の扱い
浮動小数点数の計算はどうしても誤差を含むので、なるべく避けるのがいいでしょう。
例えば、入力が のように必ず小数点以下2桁で与えられるのであれば、のように100倍して整数で処理するといいでしょう。
浮動小数点数の比較には、一般に小さい値を用いて誤差の影響を減らすテクニックが用いられます。
(確実に意図した判定をするのは不可能だろうと思います)
[table=border:1px solid #cccccc; margin: 0.5em;][tr=][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]普通の比較[/td][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]浮動小数点数の比較[/td][/tr]
[tr=][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]A == B[/td][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]fabs(A - B) < EPS[/td][/tr]
[tr=][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]A < B[/td][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]A + EPS < B[/td][/tr]
[tr=][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]A <= B[/td][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]A < B + EPS[/td][/tr][/table](EPSは1e-9~1e-7程度の小さな値)
また、言語が指定されていないようなので、JavaのBigDecimalクラスを利用するのもいいかもしれません。
例えば、入力が のように必ず小数点以下2桁で与えられるのであれば、
#include <stdio.h>
#include <stdlib.h>
/*
読み取り成功と判定したらresultが指す場所に格納して真を返す
読み取り失敗と判定したら偽を返す
*/
int read_number(int *result) {
int a, b;
if (scanf("%d.%d", &a, &b) != 2) return 0;
*result = a * 100 + b;
return 1;
}
int main(void) {
int atai1, atai2;
/* ||演算子は必ず左辺から評価される */
if (!read_number(&atai1) || !read_number(&atai2)) return 1;
if (abs(atai1 - atai2) <= 1) {
puts("YES");
} else {
puts("NO");
}
return 0;
}
浮動小数点数の比較には、一般に小さい値を用いて誤差の影響を減らすテクニックが用いられます。
(確実に意図した判定をするのは不可能だろうと思います)
[table=border:1px solid #cccccc; margin: 0.5em;][tr=][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]普通の比較[/td][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]浮動小数点数の比較[/td][/tr]
[tr=][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]A == B[/td][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]fabs(A - B) < EPS[/td][/tr]
[tr=][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]A < B[/td][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]A + EPS < B[/td][/tr]
[tr=][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]A <= B[/td][td=border:1px solid #cccccc; padding: 0.1em 0.2em;]A < B + EPS[/td][/tr][/table](EPSは1e-9~1e-7程度の小さな値)
#include <stdio.h>
#include <math.h>
#define EPS 1e-9
int main(void) {
double atai1, atai2;
if (scanf("%lf%lf", &atai1, &atai2) != 2) return 1;
if (fabs(atai1 - atai2) < 0.01 + EPS) {
puts("YES");
} else {
puts("NO");
}
return 0;
}
import java.math.BigDecimal;
import java.util.Scanner;
class Main {
public static void main(String[] args) {
BigDecimal atai1, atai2;
Scanner sc = new Scanner(System.in);
atai1 = sc.nextBigDecimal();
atai2 = sc.nextBigDecimal();
if (atai1.subtract(atai2).abs().compareTo(new BigDecimal("0.01")) <= 0) {
System.out.println("YES");
} else {
System.out.println("NO");
}
}
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)