我需要能够在我的 C 开发环境下使用浮点运算(CPU:~12 MHz 摩托罗拉 68000)。标准库不存在,这意味着它是一个简单的 C 并且不 - 由于其他几个问题,它不是 gcc
我尝试编译 SoftFloat 库和另一个 68k 特定的 FP 库(此时我不知道它的名称),但是对于这个特定平台,它们的依赖关系无法解决 - 主要是由于 libc 的缺陷。我花了大约 8 小时试图克服链接问题,直到我知道我无法再进一步。
但是,只花了半个小时就想出并实现以下一组函数,这些函数充分模拟了我的需要的浮点功能。
基本思想是小数部分和非小数部分都是 16 位整数,因此没有位操作。非小数部分的范围为 [-32767, 32767] 和小数部分 [-0.9999, +0.9999] - 这给了我们 4 位数的精度(足以满足我的浮点需求 - 尽管很浪费)。
在我看来,这可以用来制作更快、更小(仅 2 字节大)的浮点替代版本,范围为 [-99, +99] 和 [-0.9, +0.9]
这里的问题是,除了 IEEE 之外,还有哪些其他技术可以使用定点功能来实现基本的浮点功能 ( + - * /
)?
稍后,我将需要一些基本的三角函数,但是网上有很多资源。
- 由于硬件有 2 MB 的 RAM,我真的不在乎每个软浮点是否可以节省 2 个字节(例如,通过在 int 中保留 9 位和 7 位)。因此 - 4 个字节就足够了。
- 此外,通过简要查看 68k 说明手册(以及每条指令的周期成本),我做了一些早期观察:
- 位移很慢,除非性能至关重要(这里不是这种情况),否则我更喜欢轻松调试我的软浮点库而不是 5 个周期更快的代码。此外,由于这是 C 而不是 68k ASM,因此速度显然不是关键因素。
- 8 位操作数与 16 位一样慢(在大多数情况下给或取一个周期),因此为了性能而压缩浮点数似乎没有多大意义。
您建议在 C 中使用定点实现浮点而不依赖于其他库/代码的哪些改进/方法?
也许可以使用不同的方法并同时对压裂和非压裂零件进行操作?
这是代码(仅使用计算器测试),请忽略函数中间的 C++ - 类似声明和初始化(稍后我将重新格式化为 C 样式):
inline int Pad (int f) // Pad the fractional part to 4 digits
{
if (f < 10) return f*1000;
else if (f < 100) return f*100;
else if (f < 1000) return f*10;
else return f;
}
// We assume fractional parts are padded to full 4 digits
inline void Add (int & b1, int & f1, int b2, int f2)
{
b1 += b2;
f1 +=f2;
if (f1 > 9999) { b1++; f1 -=10000; }
else if (f1 < -9999) { b1--; f1 +=10000; }
f1 = Pad (f1);
}
inline void Sub (int & b1, int & f1, int b2, int f2)
{
// 123.1652 - 18.9752 = 104.1900
b1 -= b2; // 105
f1 -= f2; // -8100
if (f1 < 0) { b1--; f1 +=10000; }
f1 = Pad (f1);
}
// ToDo: Implement a multiplication by float
inline void Mul (int & b1, int & f1, int num)
{
// 123.9876 * 251 = 31120.8876
b1 *=num; // 30873
long q = f1*num; //2478876
int add = q/10000; // 247
b1+=add; // 31120
f1 = q-(add*10000);//8876
f1 = Pad (f1);
}
// ToDo: Implement a division by float
inline void Div (int & b1, int & f1, int num)
{
// 123.9876 / 25 = 4.959504
int b2 = b1/num; // 4
long q = b1 - (b2*num); // 23
f1 = ((q*10000) + f1) / num; // (23000+9876) / 25 = 9595
b1 = b2;
f1 = Pad (f1);
}