嗯,这根本不是一个优化问题。
我正在写一个(现在)简单的Linux内核模块,我需要找到一些位置的平均值。这些位置存储为浮点(即float
)变量。 (我是整个事情的作者,所以我可以改变它,但我宁愿保持浮动的准确性而不是参与其中,如果我可以避免它。)
现在,这些位置值仅存储(或至少用于)内核中的存储空间。一个用户应用程序写入这些数据(通过共享内存(我正在使用RTAI,所以我在内核和用户空间之间共享内存))和其他人从中读取数据。我假设浮点变量的读写不会使用FPU,所以这是安全的。
安全的,我的意思是avoiding FPU in the kernel,更不用说某些系统甚至可能没有FPU。我不会使用kernel_fpu_begin/end,因为这可能会破坏我的任务的实时性。
现在在我的内核模块中,我真的不需要太多的精确度(因为无论如何都是平均位置),但我需要它说0.001。 我的问题是,如何在不使用FPU的情况下将浮点数转换为整数(原始数字的1000倍)?
我想过从float的位模式手动提取数字,但我不确定这是不是一个好主意,因为我不确定endian-ness是如何影响它的,或者即使所有架构中的浮点都是标准的
答案 0 :(得分:5)
SoftFloat软件包的功能float32_to_int32
完全符合您的要求(它在软件中实现IEEE 754)。
最后,无论如何在内核中使用某种浮点支持(无论是硬件还是软件)都是有用的,因此在项目中包含这一点很可能是一个明智的决定。它也不是太大。
答案 1 :(得分:4)
如果你想告诉gcc使用软件浮点库,显然有一个开关,虽然在标准环境中可能不是交钥匙:
Using software floating point on x86 linux
事实上,本文建议使用-msoft-float
编译linux内核及其模块:
http://www.linuxsmiths.com/blog/?p=253
那就是说,@ PaulR的建议似乎最明智。如果你提供的API可以进行你喜欢的任何转换,那么我不明白为什么它比任何其他更糟糕。
答案 2 :(得分:2)
实际上,我认为您应该更改模块的API以使用已经采用整数格式的数据(如果可能)。当你不允许在内核空间中使用浮点时,在内核用户界面中使用浮点类型是个坏主意。
话虽如此,如果你使用单精度浮点数,它基本上总是IEEE 754单精度,并且字节顺序应该与整数字节顺序匹配。据我所知,Linux支持的所有arch都是如此。考虑到这一点,只需将它们视为无符号32位整数并提取位以缩放它们。如果可能的话,我会缩放1024而不是1000;这样做真的很容易。只需从第23位的尾数位(位0-22),“或”开始,如果指数(减去127的偏差之后)小于23,则向右移位,如果大于23,则向左移位。需要处理右移量大于32的情况(C不允许;你只需要特殊情况下零结果)或左移大到足以溢出的情况(在这种情况下你会可能想要钳制输出。)
如果您碰巧知道您的值不会超过特定范围,当然,您可能可以取消其中一些检查。实际上,如果你的值永远不会超过1并且你可以选择缩放,你可以选择它为2 ^ 23然后你可以直接使用((float_bits & 0x7fffff)|0x800000)
作为指数为零时的值,否则正确 - 移。
答案 3 :(得分:0)
您可以使用有理数而不是浮点数。可以在不损失精度的情况下实现操作(乘法,加法)。
如果您真的只需要1/1000精度,则可以将x * 1000存储为长整数。