gpt4 book ai didi

c - SW 浮点实现的方法有哪些?

转载 作者:太空宇宙 更新时间:2023-11-04 04:48:36 25 4
gpt4 key购买 nike

我需要能够在我的 C 开发环境下使用浮点运算(CPU:~12 MHz Motorola 68000)。标准库不存在,这意味着它是一个简单的 C 而不是 - 由于其他几个问题,它不是 gcc

我尝试编译 SoftFloat 库和另一个特定于 68k 的 FP 库(此时我忘记了它的名字),但是无法针对这个特定平台解决它们的依赖关系 - 主要是由于 libc 缺陷。我花了大约 8 个小时试图克服链接问题,直到我知道我不能再进一步了。

但是,我只花了半个小时就想出了并实现了以下一组足以满足我的需求的模拟浮点功能的函数。

基本思想是小数部分和非小数部分都是16位整数,因此没有位操作。非小数部分的范围为 [-32767, 32767],小数部分的范围为 [-0.9999, +0.9999] - 这为我们提供了 4 位精度(足以满足我的浮点需求 - 尽管有点浪费)。

在我看来,这可以用来制作一个更快、更小——只有 2 字节大——范围为 [-99,+99] 和 [-0.9,+0.9] 的 float 的替代版本

这里的问题是,还有哪些其他技术 - 除了 IEEE - 可以使用固定值实现基本的浮点功能 (+ - */) -点功能?

稍后,我将需要一些基本的三角函数,但网上有很多相关资源。

  • 由于硬件有 2 MB 的 RAM,我真的不在乎我是否可以为每个软 float 节省 2 个字节(比如 - 通过在 int 中保留 9 位和 7 位)。因此 - 4 个字节就足够了。
  • 此外,通过简要查看 68k 的说明手册(以及每条指令的周期成本),我做了一些早期观察:
    • 位移很慢,除非性能至关重要(这里不是这种情况),否则我更喜欢轻松调试我的软浮点库而不是 5 周期更快的代码。此外,由于这是 C 而不是 68k ASM,显然速度不是关键因素。
    • 8 位操作数与 16 位操作数一样慢(在大多数情况下需要一个周期),因此为了性能而压缩 float 似乎没有多大意义。

在不依赖于其他库/代码的情况下,您会提出哪些改进/方法来使用定点在 C 中实现浮点?

也许可以使用不同的方法同时对 frac 和非 frac 部分进行操作?

这是代码(仅使用计算器测试),请忽略函数中间的 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);
}

最佳答案

对于简单的定点实现,您考虑的基础是错误的。如果您使用作为小数位,会容易得多。例如整数部分使用 16 位,小数部分使用 16 位(范围 -32767/32767,精度为 1/2^16,比你的精度高很多)。

最好的部分是加法和减法很简单(只需将两部分相加即可)。乘法有点棘手:您必须注意溢出,因此它有助于在 64 位中进行乘法。您还必须在乘法后移动结果(无论小数点中有多少位)。

typedef int fixed16;

fixed16 mult_f(fixed16 op1, fixed16 op2)
{
/* you may need to do something tricky with upper and lower if you don't
* have native 64 bit but the compiler might do it for us if we are lucky
*/
uint64_t tmp;
tmp = (op1 * op2) >> 16;

/* add in error handling for overflow if you wish - this just wraps */
return tmp & 0xFFFFFFFF;
}

除法类似。

有人可能已经实现了几乎完全符合您需要的功能(或者可以通过黑客攻击使其工作),称为 libfixmath

关于c - SW 浮点实现的方法有哪些?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18341666/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com