此函数如何通过 NOT 和 AND 运算计算浮点数的绝对值?

Posted

技术标签:

【中文标题】此函数如何通过 NOT 和 AND 运算计算浮点数的绝对值?【英文标题】:How does this function compute the absolute value of a float through a NOT and AND operation? 【发布时间】:2014-05-24 16:39:05 【问题描述】:

我正在尝试了解以下代码 sn-p 的工作原理。该程序使用 SIMD 向量指令(英特尔 SSE)来计算 4 个浮点数的绝对值(因此,基本上是一个向量化的“fabs()”函数)。

这里是sn-p:

#include <iostream>
#include "xmmintrin.h"

template <typename T>
struct alignas(16) sse_t

    T data[16/sizeof(T)];
;

int main()

    sse_t<float> x;
    x.data[0] = -4.;
    x.data[1] = -20.;
    x.data[2] = 15.;
    x.data[3] = -143.;
    __m128 a = _mm_set_ps1(-0.0); // ???
    __m128 xv = _mm_load_ps(x.data);
    xv = _mm_andnot_ps(a,xv); // <-- Computes absolute value
    sse_t<float> result;
    _mm_store_ps(result.data, xv);
    std::cout << "x[0]: " << result.data[0] << std::endl;
    std::cout << "x[1]: " << result.data[1] << std::endl;
    std::cout << "x[2]: " << result.data[2] << std::endl;
    std::cout << "x[3]: " << result.data[3] << std::endl;

现在,我知道它可以工作,因为我自己运行程序来测试它。用g++ 4.8.2编译时,结果为:

x[0]: 4
x[1]: 20
x[2]: 15
x[3]: 143

三个(相关的)问题让我很困惑:

首先,怎么可能采用按位函数并将其应用于浮点数?如果我在 vanilla C++ 中尝试这个,它会告诉我这只适用于整数类型(这是有道理的)。

但是,其次,更重要的是: 它是如何工作的?在这里接受 NOT 和 AND 对您有什么帮助?在 Python 中尝试使用整数类型只会给您预期的结果:任何整数 AND -1(不是 0),只会返回该数字,但不会更改符号。那么它在这里是如何工作的呢?

第三,我注意到如果我将用于 NAND 操作的浮点值(用三个 ??? 标记)从 -0.0 更改为 0.0,程序不再给我绝对值。但是 -0.0 怎么可能存在,它有什么帮助呢?

有用的参考资料:

Intel intrinsics guide

【问题讨论】:

这是 SSE,值没有类型 - 您所做的操作决定了位模式的解释方式。这只是对符号位进行与运算。 我不确定我的标签编辑是否是最好的。关键是这个问题只对 IEEE 754 浮点表示有意义。使用 Visual C++ 暗示了这一点。但即使是特定编程语言的使用也大多是无关紧要的。也许对标签有更好感觉的人可以改进。 @Alf 我没有使用Visual C++,否则我为什么要使用gcc 编译器?我什至没有为此使用 Windows,我使用的是 Linux。所以,它肯定也可以在那里工作。 【参考方案1】:

-0.0 表示为1000...0001。因此_mm_andnot_ps(-0.0, x)2 等价于0111...111 &amp; x。这会强制 MSB(即符号位)为 0。


1。至少在 IEEE-754 中。

2. _mm_andnot_ps 内在函数并不意味着“NAND”;参见例如http://msdn.microsoft.com/en-us/library/68h7wd02(v=vs.90).aspx。

【讨论】:

以上是关于此函数如何通过 NOT 和 AND 运算计算浮点数的绝对值?的主要内容,如果未能解决你的问题,请参考以下文章

计算机组成原理——浮点数加减运算&强制类型转换

计算机组成原理——浮点数加减运算&强制类型转换

如何计算两个坐标之间的距离(没有浮点数)?

js浮点数运算封装, 起因财务部分精确计算

php浮点数精确运算之bc系列函数

JS 乘法运算出现了浮点,该怎么解决