ページ 11

計算の順序

Posted: 2012年7月08日(日) 13:53
by asdjack
AOJのvolume 0、問題番号0004の連立方程式を解く問題を解いているのですが、

コード:

#include<stdio.h>
int main()
{
	double a,b, c, d, e, f, x,y;
	while(scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f)!=EOF)
	{
		x=(e*c-b*f)/(e*a-b*d);
		y=(c-a*x)/b;
		printf("%.3f %.3f\n",x,y);
	}
}
だと wrong answer が帰ってきて

コード:

#include<stdio.h>
int main()
{
	double a,b, c, d, e, f, x,y;
	while(scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f)!=EOF)
	{
		y=(a*f-c*d)/(a*e-d*b);
		x=(c-b*y)/a;
		printf("%.3f %.3f\n",x,y);
	}
}
だと正解だと表示されました。
計算の順番が違うと答えが変わってしまう場合があるのでしょうか?
それともどこか書き間違えている部分があるのでしょうか?

Re: 計算の順序

Posted: 2012年7月08日(日) 14:10
by beatle
浮動小数点数は実数型ではなくて小数型でして、ある桁数までしか保持できません。
浮動小数点数の演算には誤差がつきものです。

AOJの問題文を読むと、小数点以下第4位を四捨五入しろと書いてありますが、その処理が見当たりません。
printfが四捨五入してくれるという保証もありませんし。

このあたりが複雑に絡み合った問題なのかもしれませんね。

Re: 計算の順序

Posted: 2012年7月13日(金) 02:40
by かずま
asdjack さんが書きました:計算の順番が違うと答えが変わってしまう場合があるのでしょうか?
IEEE754 の浮動小数点の内部表現で、0 は +0.0 と -0.0 の 2通りあります。
printf("%.3f", -0.0); は -0.000 となることを確認してみてください。
AOJ は結果の文字列を単純比較しているだけで、0.000 しか認めていないのではないでしょうか?

if (x == -0) x = 0; を追加してみてください。y も同様。
実は、if (x == 0) x = 0; と書いてもかまいません。x が -0 でも -0 == 0 は 1 になります。

Re: 計算の順序

Posted: 2012年7月13日(金) 16:29
by asdjack
かずま さんが書きました: if (x == -0) x = 0; を追加してみてください。y も同様。
実は、if (x == 0) x = 0; と書いてもかまいません。x が -0 でも -0 == 0 は 1 になります。
通らなかったXからの解法でこの処理を入れたところ、ちゃんと通りました。
Xから計算すると-0でエラーが出てYから計算するとちゃんとXが0になって通ったんだと思われます
beatleさんの言うとおり、四捨五入の処理が無いのに通ってしまいましたが、これはテストデータの中に四捨五入の必要があるものが無かったのかもしれません。
かずまさん beatleさん ご回答ありがとうございました。