Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 当给定浮点数时,如何避免FPU?_C_Linux Kernel_Floating Point_Fpu_Rtai - Fatal编程技术网

C 当给定浮点数时,如何避免FPU?

C 当给定浮点数时,如何避免FPU?,c,linux-kernel,floating-point,fpu,rtai,C,Linux Kernel,Floating Point,Fpu,Rtai,这根本不是一个优化问题 我正在编写一个(目前)简单的Linux内核模块,需要找到一些位置的平均值。这些位置存储为浮点(即float)变量。(我是整件事的作者,所以我可以改变这一点,但如果可以避免的话,我宁愿保持float的精度,也不要卷入其中) 现在,这些位置值存储(或至少用于)在内核中,只是为了存储。一个用户应用程序写入这些数据(通过共享内存(我使用的是RTAI,所以是的,我在内核和用户空间之间有共享内存))而其他应用程序从中读取数据。我假设从浮点变量读写不会使用FPU,所以这是安全的 说到安

这根本不是一个优化问题

我正在编写一个(目前)简单的Linux内核模块,需要找到一些位置的平均值。这些位置存储为浮点(即
float
)变量。(我是整件事的作者,所以我可以改变这一点,但如果可以避免的话,我宁愿保持float的精度,也不要卷入其中)

现在,这些位置值存储(或至少用于)在内核中,只是为了存储。一个用户应用程序写入这些数据(通过共享内存(我使用的是RTAI,所以是的,我在内核和用户空间之间有共享内存))而其他应用程序从中读取数据。我假设从浮点变量读写不会使用FPU,所以这是安全的

说到安全,我的意思是,更不用说一些系统甚至可能没有FPU。我不打算使用,因为这可能会破坏我任务的实时性

现在在我的内核模块中,我真的不需要太多的精度(因为位置是平均的),但我需要它达到0.001我的问题是,如何在不使用FPU的情况下将浮点数转换为整数(原始数的1000倍)?


我考虑过从浮点的位模式中手动提取数字,但我不确定这是否是一个好主意,因为我不确定endian ness对它有何影响,甚至不确定所有体系结构中的浮点是否都是标准的。

如果你想告诉gcc使用软件浮点库,显然有一个开关,尽管在标准环境中可能不是交钥匙:

事实上,本文建议linux内核及其模块已经使用
-msoft float
编译:

尽管如此,@PaulR的建议似乎是最明智的。如果你提供的API可以进行你喜欢的任何转换,那么我不明白为什么它比其他任何东西都更难看。

该软件包的函数
float32\u to\u int32
正是你想要的(它在软件中实现了IEEE 754)


总之,在内核中提供某种浮点支持(无论是硬件还是软件)是很有用的,因此在项目中包含这一点很可能是一个明智的决定。它也不太大。

你可以用有理数代替浮点数。运算(乘法、加法)也可以在不损失精度的情况下实现


如果您真的只需要1/1000精度,您可以将x*1000存储为一个长整数。

真的,如果可能的话,我认为您应该更改模块的API以使用已经是整数格式的数据。当您不允许在内核空间中使用浮点时,在内核用户界面中使用浮点类型只是一个坏主意

也就是说,如果你使用单精度浮点,它基本上总是IEEE 754单精度,并且endianness应该匹配整数endianness。据我所知,这适用于所有archs Linux支持。记住这一点,只需将它们视为无符号32位整数,并提取位以缩放它们。如果可能的话,我会按1024而不是1000进行缩放;这样做真的很容易。只需从尾数位(位0-22)开始,如果指数(减去127的偏差)小于23,则右移,如果指数大于23,则左移。您需要处理右移位量大于32的情况(C不允许;您必须在特殊情况下处理零结果),或者左移位量足够大以至于溢出的情况(在这种情况下,您可能需要钳制输出)


当然,如果您碰巧知道您的值不会超过某个特定范围,那么您可能可以消除其中一些检查。事实上,如果您的值从未超过1,并且您可以选择缩放,您可以选择它为2^23,然后您可以直接使用
((float_bits&0x7fffff)| 0x800000)
作为指数为零时的值,或者右移。

为什么不首先将值存储为1000x整数?@PaulR我想OP考虑过这一点,因为他说他可以改变,但他宁愿保持精度,所以他问是否有其他方法可以做到这一点。好问题,就我个人而言,我也想知道。@PaulR,这正是我现在想做的事情,因为其他任何方式似乎都没有希望。不过,我不想错过一个好的解决方案。定点数字很容易求和和和除法——你甚至不需要分开整数和小数部分。对于加法、减法以及乘/除整数,你只需将定点数字视为整数。在对两个定点数字进行乘法/除法时,只需处理隐式小数点,即使这样,它也只是一个额外的移位。我在同一篇文章中看到,在构建内核模块时启用了-msoft float。我对uuu div.有未定义的引用。。对于之前的64位除法,但不是浮点,所以我认为应该是相同的(浮点除法使用外部函数,但不是加法)。但我没有测试它。尽管如此,对于64位除法,仍然有
do\u div
,但对于浮点数,我相信不存在这样的功能。它是否偶然发现了
\u fixsfdi
?我会接受你的答案(但在一段时间后,以防其他答案出现),即使我可能会以固定的精度将浮动更改为
long
s。这很有趣。不过我需要问一件事。是否确定所有的FPU(至少在所有能够运行linux内核的计算机上)都使用IEEE 754标准?@Shazbaz:不,linux内核支持的架构比IEEE 754更多,但supportign IEEE 754是一个良好的开端(现在几乎所有的架构都使用它,值得注意的例外是IBM大型机)。