使用浮点运算对整数数据进行右移运算?

Posted

技术标签:

【中文标题】使用浮点运算对整数数据进行右移运算?【英文标题】:Rotate Right operation on integer data using floating point operations? 【发布时间】:2011-05-09 04:58:09 【问题描述】:

我想取一个无符号整数表示的值,并以某种方式使用浮点运算执行旋转右移按位运算。

看看这里使用的聪明:http://en.wikipedia.org/wiki/Fast_inverse_square_root 这使用了一个魔术值和一些技巧来使用整数运算对浮点数执行运算。我想要的是相反的;我使用的硬件针对浮点进行了高度优化,但在整数运算方面表现不佳。算法是sha256,大量使用了右旋转操作。

【问题讨论】:

【参考方案1】:

想到了两种方法:

获取包含整数的位,将它们填充到一个期望包含相同位数的浮点数的变量中,然后对这些位进行操作,就好像它们是浮点数一样。希望硬件有一些浮点运算,对这些位的运算方式与 SHA256 使用的整数运算相同。 将整数填充到具有更多位的浮点变量中(例如,将 Int32 放入可以容纳 53 位而不会丢失精度的 Double 中),然后使用数学运算实现右旋转操作。

第一个选项不太可能奏效。如果您的硬件基于 IEEE 754 浮点标准(最常见的浮点表示标准),则浮点数存储为位域;例如,double 有 1 个符号位、11 个指数位和 53 个小数位。不会有任何操作将符号位的值转移到指数位槽之一。然后是具有特殊含义的位模式,并在整个操作中携带该含义,例如 NaN 和无穷大。因此,整个想法可能是行不通的。

我不确定第二种方法是否可行;您将需要完全控制诸如舍入行为之类的事情,并且想要说服自己您的浮点值中有正确的位数,并且您绝对需要大量测试来说服自己它正在得到整个输入范围的预期输出。但是这里有。

一个向右旋转的操作——比如说,x ror y——就这样失败了。设 b 为 x 中的位数。我假设一切都是使用无符号算术完成的,因为它使逻辑更简单。

我们从x ror y开始。 这可以表示为右移、左移和 OR,如 (x shr y) or (x shl (b - y))。 Shr 与除以 2 的幂相同。 Shr 会丢弃掉下端的任何位,因此我们可以使用 floor 函数来模拟它。所以现在我们有了floor(x / 2^y) or (x shl (b - y))。 Shl 与乘以 2 的幂相同。 Shl 丢弃掉掉上端的所有位,我们可以通过乘法模 2^b 来模拟。这给了我们floor(x / 2^y) or ((x * 2^(b - y)) mod 2^b)。 由于 shl 和 shr 的结果是不相交的(它们影响结果中的不同位),or 也可以通过加法来完成。所以现在我们有了整个旋转操作的数学符号:floor(x / 2^y) + ((x * 2^(b - y)) mod 2^b)

现在只需在 SHA256 执行向右旋转操作的每个位置插入该公式,看看它是否比整数运算更快。这似乎不太可能但并非不可能——将两个具有不同指数的浮点数相加将需要在 FP 硬件内部进行快速移位操作,即使整数硬件没有快速移位也是如此。

【讨论】:

以上是关于使用浮点运算对整数数据进行右移运算?的主要内容,如果未能解决你的问题,请参考以下文章

具有浮点运算的一致整数除法

Shell 脚本浮点运算

使用整数运算的浮点加法

为啥C++里面浮点与整数相乘的结果跟在计算器里的不一样呢?浮点我选的float

java基础之java程序基础--之浮点运算

STM32 M0和M3内核单片机做浮点除法运算和整型除法运算,分别的用时。希望能给大概数据参考。