- PR -

C言語の桁落ちについて

1
投稿者投稿内容
soccer
ベテラン
会議室デビュー日: 2003/09/17
投稿数: 99
投稿日時: 2004-01-15 20:01
このセクションでお聞きしていいのか判りませんが、
もし、ご回答頂ければ幸いです。

#include<stdio.h>
int main()
{
double tan;
double sum_su;
long kin;

sum_su = 800;
tan = 275.96;
kin = sum_su*tan;
printf("* kin=[%ld]\n",kin);
}
上記のCのプログラムでkinを表示すると220767ですが
実際は、220768になります。
このような場合の対応方法は、何かあるのでしょうか?
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2004-01-15 20:53
6年前くらい制御系の仕事をしていた時は、整数演算で済ませるようにしていました。
そのとき、桁あふれしそうなら、long long型とかを利用してました。

見当違いの回答になっていたら、すいません。

コード:
#include<stdio.h> 
int main() 
{ 
    long tan; 
    long sum_su; 
    long kin; 

sum_su = 800; 
tan = 27596; 
kin = (sum_su*tan) / 100; 
printf("* kin=[%ld]\n",kin); 
} 


ちいにぃ
大ベテラン
会議室デビュー日: 2002/05/28
投稿数: 244
投稿日時: 2004-01-15 21:20
double -> longへの変換時に切り捨てられているのかもしれません。

Cygwinで次のプログラムを実行してみたところ、
コード:
#include<stdio.h>
int main()
{
	double tan;
	double sum_su;
	long kin;
	double kin_double;

	sum_su = 800;
	tan = 275.96;
	kin_double = sum_su*tan;
	kin = sum_su*tan;
	printf("* kin_double=[%16.16lf]\n", kin_double);
	printf("* kin=[%ld]\n", kin);

	return 0;
}



結果はこのようになりました。

* kin_double=[220767.9999999999708962]
* kin=[220767]

そこで大雑把ですが、切り捨てられているのなら、
下記のように .5 を足して(=四捨五入して)やればよいかと。
コード:
	kin = sum_su*tan + .5;


未記入
ぬし
会議室デビュー日: 2002/03/28
投稿数: 255
投稿日時: 2004-01-15 21:29
>上記のCのプログラムでkinを表示すると220767ですが
>実際は、220768になります。
>このような場合の対応方法は、何かあるのでしょうか?
多分,小数点以下の誤差の影響じゃないですか.

・オーバーフローが起こらないとして,
先に100をかけてからかけ算して,その結果を100で割る.

・多倍長を使って計算する.

あと,そのような誤差が許されない問題の場合は,いずれにせよ浮動
小数点は向いていません.根本的な原因は設計ミスです.
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-01-16 09:44
unibon です。こんにちわ。

C ではなく JavaScript ですが、つぎのような補正用のプログラムを書いたことがあります。
http://www.geocities.co.jp/SiliconValley/4334/unibon/javascript/decimalcalculate.html
ぶっちゃけていうと、.99999 のようにあまりにも 9 が続く(あるいは .00001 のように 0 が続く)なら、誤差だとみなして捨てます。
C に変換するのも簡単でしょう。

なお、C だと浮動小数点の64ビットや32ビットのビットパターンを直接見ることもできますので、もっと違ったソリューションもあるのかもしれません。たとえば、2進数→10進数変換の段階で有効桁数を抑えるなどです。
#VB だとそうやってますので誤差があらわに見えないです。そのため余計ややこしいとも言えますが。


#あとで誤字修正。

[ メッセージ編集済み 編集者: unibon 編集日時 2004-01-16 09:45 ]
1

スキルアップ/キャリアアップ(JOB@IT)