自己答一个:后来考虑了一下其实有asin就行了,用了查表+线性插值的方案。查找表只用了0到90度,间隔5.625度的17个点, 再乘以0xffff,如下:
const unsigned short sintab[] = { 0x0000, 0x1918, 0x31f1, 0x4a50, 0x61f7, 0x78ad, 0x8e39, 0xa267, 0xb504, 0xc5e3, 0xd4da, 0xe1c5, 0xec82, 0xf4f9, 0xfb14, 0xfec3, 0xffff };
然后查表+线性插值,输入限定在0~0xffff。
int int_asin(int x) { int ret, sign=1; if(x<0) { x=-x; sign=-1; // 处理负数 } for(int i = 0; i < sizeof(sintab) / sizeof(sintab[0]); i++) { if(sintab[i] <= x && x <= sintab[i + 1]) { ret = (((x - sintab[i]) * 90 / (sintab[i+1] - sintab[i]) + i * 90) ) >> 4; break; } } return ret * sign; }
实测算出来的角度值和math库的asin基本相符,个别情况差1度。
int main(void) { for(int i = -90; i <= 90; i++) { int y = (sin(i * 3.141593 / 180.0) * 65535.0); int x1 = int_asin(y); float x2 = asin(y / 65536.0) * 180.0 / 3.141593; printf("%d %d %.3f %d
", i, x1, round(x2), x1-round(x2)); } return 0; }