通常,我们使用微控制器在机器人中执行操作,但是需要用十进制进行一些计算。使用浮点变量非常慢,因为会自动包含软件浮点库(除非您有高端微控制器)。因此,我们通常使用定点算术。

每次执行此操作时,我都只使用整数,并记住小数点在哪里。但是,确实要确保所有内容都是一致的,特别是当计算涉及小数点位于不同位置的变量时。

我实现了定点atan2函数,但是因为尝试压缩最后一滴有限精度(16位)的数据时,我经常会更改小数点位置的定义,并且随着我对其进行调整,它也会发生变化。另外,我还有一些常量(作为准查找表),它们本身在某个地方有一个隐含的小数点。

我想知道是否有更好的方法。是否有一个库或一组宏,可以简化定点变量的使用,简化混合变量之间的乘法和除法,并允许声明十进制数或常量表达式,但在编译时自动转换为所需的定点表示形式时间?

评论

我认为这实际上对于stackoverflow更好,因为该解决方案是通用的,与机器人技术无关。

@Jakob-请注意,这两个问题都没有建设性。

这种事情会使C ++对嵌入式系统非常有用。模板会自动生成正确和最佳的代码。

我可以看看您的atan功能吗?我正在尝试解决学术研究中的浮点到定点转换问题,很高兴对此有所了解。

@ronalchn Arduino(一种AVR微型)语言的某些部分用C ++实现。还有一个AVR C ++库。还有该线程供编译器使用。

#1 楼

如果我们能告诉编译器每个定点输入变量的范围和精度(可能没有两个在相同位置的小数点)会很好,并且它会自动(在编译时)使用正确的范围以及在一系列计算中对中间值和最终值进行的精度和比例缩放操作。
有传言说,有可能在Ada编程语言或C ++模板中做到这一点。

A,我所看到的最接近的是定点运算库,程序员需要您手动选择正确的表示形式,并手动验证每个操作是否保持足够的范围和精度。
有时它们会进行乘法运算和混合变量之间的除法更容易。
例如:




AVRfix:用于s15.16,s7.24和s7.8中的定点计算的库格式,完全用ANSI C

嵌入式系统编写:定点FFT列出了一些用于修复的库ed点FFT计算
AN617:Microchip PICmicro的定点例程

SourceForge上的“定点”项目。
gcc内置了定点库ab


TI IQMath库(和来源-谢谢Embedded.kyle)。


评论


$ \ begingroup $
几乎可以肯定,使用C ++模板可以做到这一点。
$ \ endgroup $
– Rocketmagnet
2012年10月31日15:24

$ \ begingroup $
我实际上正在做一些事情,就像您的“如果...会很好”评论一样。它是gcc的插件,可将浮点C代码转换为定点,从而优化沿途的所有二进制点位置。我有一篇论文提交给ACM期刊,还有另一篇论文正在准备中。如果您有用于atan函数的C代码,我将很高兴为您提供帮助...我可以还给您使用整数变量并完成所有定点操作的C代码。
$ \ endgroup $
–乔·哈斯(Joe Hass)
2012年11月7日20:52

$ \ begingroup $
+1比我的答案更完整。我已经在我的链接中编辑了该链接,以包括指向某个地方的链接,该地方请求源代码来解决Mark Booth的评论。您可能还需要更新链接。我自己做,但是建议的编辑正在排队中,并且阻止了我。
$ \ endgroup $
–embedded.kyle
2012年11月8日13:31

$ \ begingroup $
@Rocketmagnet最肯定的是可以使用模板来实现定点,请参见FixedPoints(免责声明:我写了这个,现在还很“年轻”)。
$ \ endgroup $
–法老王
18-2-24在10:42



$ \ begingroup $
gcc链接“ a”已损坏
$ \ endgroup $
– Lesto
19年3月7日在17:10

#2 楼

我已经使用TI IQMath库在其定点DSP上实现了虚拟浮点。


Texas Instruments TMS320C28x IQmath库是高度优化和高精度的集合。 C / C ++程序员的数学函数可以将浮点算法无缝移植到TMS320C28x器件上的定点代码中。这些例程通常用于计算密集型实时应用程序,在这些应用程序中,最佳的执行速度和高精度至关重要。通过使用这些
例程,您可以比用标准ANSI C语言编写的等效代码更快地实现执行速度。此外,通过
提供即用型高精度功能,TI IQmath库可以
显着缩短您的DSP应用开发时间。


它使用了一些TI特定的东西但是我也以该代码为基础在其他微控制器上实现了虚拟浮点数学运算。移植需要一些工作,但比从头开始要容易得多。

评论


$ \ begingroup $
@downvoter关心评论我的答案有什么问题吗?
$ \ endgroup $
–embedded.kyle
2012年10月29日12:37

$ \ begingroup $
+1:该库比他现在使用的库更好(“仅使用整数”)。它并不能解决原始问题所要求的一切,但是我认为这样的回答(有用但不是完整的解决方案)不应该被否决-除非确实存在完整的解决方案(在这种情况下,我对此表示怀疑) )。
$ \ endgroup $
–大卫·卡里(David Cary)
2012年10月31日15:12

$ \ begingroup $
在我看来,仅针对单个设备的答案仅在啤酒中是免费的,而在语音中是免费的,这对将来的访问者来说用途有限。
$ \ endgroup $
– Mark Booth♦
2012年11月8日,11:51

$ \ begingroup $
@MarkBooth我将链接从C28x库更改为C64x库。如果您点击该链接,则可以请求源代码。您需要公司或大学的电子邮件才能访问。仍然免费,如啤酒和演讲。您只需要举手并等待被呼叫就可以讲话。有点烦人,但是一旦有了源代码,它就可以适应您喜欢的任何处理器。
$ \ endgroup $
–embedded.kyle
2012年11月8日13:14

$ \ begingroup $
感谢@ embedded.kyle源代码绝对比仅二进制文件要好,但是如果许可证仅允许您以有限的方式使用它,那么它仍然很少使用。根据C6x软件库页面,该资源仅根据TI商业许可证发布,几乎可以肯定,该许可证不是像语音那样免费的。
$ \ endgroup $
– Mark Booth♦
2012年11月8日13:30



#3 楼

Binary Scaling(又名B缩放)有许多实现(我没有立即意识到的库)

在此,您需要牢记(或更好地记录代码) ...)小数点所在的位置,使用移位将小数点向上或向下移动。

我在国防项目的汇编器中使用了B缩放,即使在最小的CPU上也是如此。证明它适用于其他任何东西...

评论


$ \ begingroup $
大概是这样的,但是我从未见过它被称为b缩放。我将其视为固定点-小数点永远不会浮动,因为即使在计算过程中小数点可能会更改,任何一个变量始终会将小数点固定在特定位置
$ \ endgroup $
– ronalchn
2012年10月26日在21:01



#4 楼

如果使用整数记住“点”的位置,则它们是使用浮点算术的一种。定点,确实有定点。

我怀疑对于每个函数,都会有不同的“预处理”以使您的“浮点”数适合该函数。例如,对于atan,您需要对数字进行移位,以使其小数点与定点函数的小数点匹配。对于cos,您可能希望在$ \ pi $和$-\ pi $的范围内获取它,然后对其进行移位。

这取决于您的应用程序所需的值范围,但您可能想要完全移动到定点表示。也就是说,例如,不要保留这样的数字:

struct num
{
    uint16_t number;
    uint16_t decimal_point;
};


其中number是整数,而decimal_point说小数点在哪里,您可以存储它像这样:

struct num
{
    uint16_t integer;
    uint16_t fraction;
};


其中整数为integer.fraction,具有相同的内存使用量,更大的值范围并且通常更易于使用。

评论


$ \ begingroup $
实际上存储小数点会使它更像是浮点数。通常,小数点是在编译时定义的,您可以根据操作在表示形式之间进行切换。
$ \ endgroup $
–雅各布
2012年10月26日上午10:11

$ \ begingroup $
我不是要记住存储在变量中,而是要记住如何解释结果(通过知道小数点在哪里)
$ \ endgroup $
– ronalchn
2012年10月26日10:16

$ \ begingroup $
@ronalchn,我知道了。您的意思是带有#define,对吗?我以为您实际上存储了它,它可能根据您的数字大小而有所不同。
$ \ endgroup $
– Shahbaz
2012年10月26日在11:21

$ \ begingroup $
@ronalchn-您是否正在考虑B缩放? (请参阅我的答案)
$ \ endgroup $
–安德鲁♦
2012年10月26日19:00