我在沒有浮點或數學庫的 MCU 上使用 C 語言,我擁有的最大型別是int32_t.
我在這樣的圖表上有一個(x, y)坐標 ( int8_t):

用戶可以說他們想按X度旋轉點的位置(比方說90°)。這總是相對于中心。
最終結果應該是(64, 32):

我需要沒有進入數學庫(不ATAN2,罪等)的精度我需要的是在落實這在C0.2°增量(因此0.2°,40.8°等都是有效的。)
uj5u.com熱心網友回復:
另一種選擇是為 sin(x) 的第一象限預先計算查找表。
由于您需要 0.2° 度的精度,因此表中將有 450 個值。將它們保留為 int32 定點,帶有 16 位小數部分。
如果你有那個表,你可以使用 16.16 定點數學來計算 2x2旋轉矩陣,并將你的點乘以矩陣。
如果您有許多點以相同的角度旋轉,則可能比反正切快。用該矩陣轉換一個點只需要 4 次移位(兩個用于輸入,兩個用于輸出)、4 次 int32 乘法和 2 次 int32 加法。
PS 如果你真的記憶體不足,使用 17.15 定點而不是 16.16,這樣查找表只需要 2 個位元組/條目,整個表需要 900 個位元組。
uj5u.com熱心網友回復:
OP 正在尋找一個完整的圓非math.h atan2().
先解決一個更簡單的問題。以“我需要的精度為 0.2° 增量”找到[0.0 到 1.0]的反正切值。結果將是 [0.00 ... 45.00] 度或至少45/0.2 (225) 個不同的值。
在 0 到 45 度范圍內,反正切(x) 函式曲線平緩。當 x == 0 到大約 0.6187 ... x=45 度時,它的斜率(以弧度/x 為單位)接近 1.0。足以制作大約 225/0.6187 (364) 個條目的統一查找表,以實作 0.02 度的精度。
arctan_lu[SCALE_INDEX 1]使用round(radians2degrees(atan(1.0*index/SCALE_INDEX))*100.0)來自 Excel 或其他 C 程式的預先計算的值形成查找表。
// Number of table lookup entries
#define SCALE_INDEX 364
const int arctan_lu[SCALE_INDEX 1] = { 0, ..., 4500 }; // Values from pre-computation
然后縮放查找索引并查找答案。
// Return arc-tangent in centi-degrees [0 ... 4500]
// for an x, y in the first octant: 0 < y < x < INT32_MAX/SCALE_INDEX
//
int arctagent_primary(int32_t y, int32_t x) {
int index = SCALE_INDEX*y/x;
return arctan_lu[index];
}
現在有了第一個八分圓的解決方案,可以操縱x,y其他八分圓。
// Return arctangent in centi-degrees [0 ... 36000]
// for all x, y
unsigned arctagent_primary(int32_t y, int32_t x) {
if (y < 0) {
return 36000 - arctagent_primary(-y, x);
}
if (x < 0) {
return 18000 - arctagent_primary(y, -x);
}
if (y >= x) {
return 9000 - arctagent_primary(x, y);
}
if (y > 0) {
retrun arctagent_primary(y, x);
}
return 0; // x,y both 0
}
在或大于arctagent_primary()時所需的額外作業。只需將它們一起縮小即可。xyINT32_MAX/SCALE_INDEX
while (x > INT32_MAX/SCALE_INDEX || y > INT32_MAX/SCALE_INDEX) {
x /= 2;
y /= 2;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/323476.html
