« 【JavaSE】多角形との当たり判定 | トップページ | Thunderbirdの迷惑メールフィルタ設定がリセットされる »

2010年8月 9日 (月)

【C】固定小数点数三角関数

整数演算のみを使った固定小数点数の三角関数を実装してみた。

結論から言うと精度が低いし使い勝手も悪い。

しかしせっかくなので覚え書きとして残す。

#include <stdio.h>
#include <math.h>

#ifndef M_PI
#define M_PI   3.1415926535
#endif

#define FIXBITN   14
#define FIXUNUS   (1L<<FIXBITN)

long Fix_mul(long a, long b)
{
#if 1
	long ah = a / FIXUNUS;
	long al = a - ah * FIXUNUS;
	long bh = b / FIXUNUS;
	long bl = b - bh * FIXUNUS;
	long val = 0;
	val += al * bl / FIXUNUS;
	val += ah * bl;
	val += a * bh;
	return val;
#else
	return (long)((long long)a * b / FIXUNUS);
#endif
}

long Fix_sin(long rad)
{
	long ans, t, rad2;
	int n;

	ans = t = rad;
	n = 2;

	rad2 = Fix_mul(rad, rad);

	for (;;) {
		t = - Fix_mul(t, rad2)/((2*n-2)*(2*n-1));
		if (t == 0) break;
		ans = ans + t;
		n++;
	}
	return ans;
}
long Fix_cos(long rad)
{
	long ans, t, rad2;
	int n;

	ans = t = FIXUNUS;
	n = 1;

	rad2 = Fix_mul(rad, rad);

	for (;;) {
		t = - Fix_mul(t, rad2)/((2*n)*(2*n-1));
		if (t == 0) break;
		ans = ans + t;
		n++;
	}
	return ans;
}
long Fix_atan(long x)
{
	long ans, t, s, x2;
	int n;

	ans = t = x;
	n = 3;

	x2 = Fix_mul(x, x);

	for (;;) {
		t = - Fix_mul(t, x2);
		s = t/n;
		if (s == 0) break;
		ans = ans + s;
		n+=2;
	}
	return ans;
}

int main(void)
{
	int i;
	double d;
	printf("\n[sin]   固定      浮動\n");
	for (i=0; i<=360; i+=10) {
		printf("%3d度:", i);
		printf(" % 8f", (double)Fix_sin((long)(i*M_PI*FIXUNUS/180))/FIXUNUS);
		printf(" % 8f\n", sin(i * M_PI / 180));
	}
	printf("\n[cos]   固定      浮動\n");
	for (i=0; i<=360; i+=10) {
		printf("%3d度:", i);
		printf(" % 8f", (double)Fix_cos((long)(i*M_PI*FIXUNUS/180))/FIXUNUS);
		printf(" % 8f\n", cos(i * M_PI / 180));
	}
	printf("\n[atan]  固定      浮動\n");
	for (d=0.0; d<1.0; d+=0.1) {
		printf("  %3.1f:", d);
		printf(" % 8f", (double)Fix_atan((long)(d*FIXUNUS))/FIXUNUS);
		printf(" % 8f\n", atan(d));
	}
	return 0;
}
    
[sin]   固定      浮動
  0度:  0.000000  0.000000
 10度:  0.173645  0.173648
 20度:  0.341980  0.342020
 30度:  0.500000  0.500000
 40度:  0.642761  0.642788
 50度:  0.766052  0.766044
 60度:  0.866028  0.866025
 70度:  0.939697  0.939693
 80度:  0.984802  0.984808
 90度:  1.000000  1.000000
100度:  0.984802  0.984808
110度:  0.939697  0.939693
120度:  0.866028  0.866025
130度:  0.766052  0.766044
140度:  0.642822  0.642788
150度:  0.500000  0.500000
160度:  0.342041  0.342020
170度:  0.173645  0.173648
180度:  0.000061  0.000000
190度: -0.173584 -0.173648
200度: -0.341919 -0.342020
210度: -0.499939 -0.500000
220度: -0.642822 -0.642788
230度: -0.766113 -0.766044
240度: -0.866028 -0.866025
250度: -0.939697 -0.939693
260度: -0.984802 -0.984808
270度: -1.000000 -1.000000
280度: -0.984802 -0.984808
290度: -0.939697 -0.939693
300度: -0.866089 -0.866025
310度: -0.766113 -0.766044
320度: -0.642822 -0.642788
330度: -0.500061 -0.500000
340度: -0.342102 -0.342020
350度: -0.173645 -0.173648
360度: -0.000122 -0.000000

[cos]   固定      浮動
  0度:  1.000000  1.000000
 10度:  0.984802  0.984808
 20度:  0.939697  0.939693
 30度:  0.866089  0.866025
 40度:  0.766113  0.766044
 50度:  0.642822  0.642788
 60度:  0.500000  0.500000
 70度:  0.342041  0.342020
 80度:  0.173645  0.173648
 90度:  0.000122  0.000000
100度: -0.173706 -0.173648
110度: -0.342041 -0.342020
120度: -0.499939 -0.500000
130度: -0.642822 -0.642788
140度: -0.766052 -0.766044
150度: -0.866089 -0.866025
160度: -0.939697 -0.939693
170度: -0.984802 -0.984808
180度: -0.999939 -1.000000
190度: -0.984802 -0.984808
200度: -0.939758 -0.939693
210度: -0.866089 -0.866025
220度: -0.766113 -0.766044
230度: -0.642822 -0.642788
240度: -0.500000 -0.500000
250度: -0.342102 -0.342020
260度: -0.173645 -0.173648
270度: -0.000061 -0.000000
280度:  0.173584  0.173648
290度:  0.341919  0.342020
300度:  0.499939  0.500000
310度:  0.642761  0.642788
320度:  0.765930  0.766044
330度:  0.866028  0.866025
340度:  0.939636  0.939693
350度:  0.984863  0.984808
360度:  0.999939  1.000000

[atan]  固定      浮動
  0.0:  0.000000  0.000000
  0.1:  0.099670  0.099669
  0.2:  0.197388  0.197396
  0.3:  0.291443  0.291457
  0.4:  0.380493  0.380506
  0.5:  0.463684  0.463648
  0.6:  0.540405  0.540420
  0.7:  0.610779  0.610726
  0.8:  0.674805  0.674741
  0.9:  0.732849  0.732815
  1.0:  0.784790  0.785398

|

« 【JavaSE】多角形との当たり判定 | トップページ | Thunderbirdの迷惑メールフィルタ設定がリセットされる »

C/C++」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




« 【JavaSE】多角形との当たり判定 | トップページ | Thunderbirdの迷惑メールフィルタ設定がリセットされる »