【问题标题】:How to obtain hexadecimal value of -nan如何获得-nan的十六进制值
【发布时间】:2018-10-30 12:25:59
【问题描述】:

我正在用 intel 内部函数编写一些代码并这样做:

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

float data[4];
__m128 val1 = _mm_set_ps1(2);
__m128 val2 = _mm_set_ps1(1);
val1 = _mm_cmpgt_ps(val1, val2);
_mm_store_ps(data, val1);

std::cout << std::hex << data[0];

我试图在 SSE 内在函数(即 -nan)中获取“真”的十六进制值,但每当我尝试打印 -nan 的十六进制值时,只会将 -nan 作为“十六进制值”。

我也尝试过使用 std::oct 和 std::dec ,但它们都不起作用。

我还尝试比较不同组合的 0xFFFFFFFF 和 data[0] 并得到:

float data[4];
__m128 val1 = _mm_set_ps1(2);
__m128 val2 = _mm_set_ps1(1);
val1 = _mm_cmpgt_ps(val1, val2);
_mm_store_ps(data, val1);

float f = 0xFFFFFFFF;
float g = 0xFFFFFFFF;
std::cout << std::dec << (data[0] == f) << "\n"; // Prints "0"

std::cout << std::dec << (data[0] == data[0]) << "\n"; // Prints "0"

std::cout << std::dec << (f == g); // Prints "1"

有什么方法可以打印出 -nan 的十六进制值,如果没有,谁能告诉我 -nan 的二进制、十六进制等值?

【问题讨论】:

  • 生成安静的 NaN。返回 double 类型的安静 NaN(非数字)值。 NaN 值用于标识浮点元素的未定义或不可表示的值,例如负数的平方根或 0/0 的结果。
  • 不是数字的东西(你知道“nan”代表“不是数字”吗?)怎么会有价值?它可能有一个实现定义的值,但这真的超出了我认为的重点。
  • 32 位浮点比较的结果是 0xFFFFFFFF 或 0,以启用用作掩码。这也是偶然的-nan。您是只对值感兴趣,还是特别对用代码打印它感兴趣?
  • @4386427 虽然存在这样的值,但它并不是 C++ 标准的一部分,因此不可移植。当一个人可以(而且应该!)使用std::isnan 时,真的没有理由依赖它。特别是考虑到可能有多个可能的值代表nan-nan
  • @Someprogrammerdude 哦,我并不想说它是 C++ 标准的一部分。它是特定系统上使用的浮点标准的一部分。无论如何,关键是 NaN 有(至少)一个可以打印的二进制模式。

标签: c++ floating-point nan


【解决方案1】:

根据 IEEE 规范,NaN 是一个浮点值,其所有 指数 位都设置为“1”。

因此,all 位设置为“1”的值也将是 NaN。

如果您想查看原始字节,只需打印原始字节:

#include <cmath>
#include <iomanip>
#include <iostream>
#include <sstream>

template<typename T>
std::string get_hex_bytes(T x) {
    std::stringstream res;
    auto p = reinterpret_cast<const unsigned char*>(&x);
    for (int i = 0; i < sizeof(x); ++i) {
        if (i)
            res << ' ';
        res << std::setfill('0') << std::setw(2) << std::hex << (int)p[i];
    }
    return res.str();
}

int main() {
    float data = NAN;
    std::cout << get_hex_bytes(data) << std::endl;
}

在 little-endian 机器上会打印如下内容:

00 00 c0 ff

附: float f = 0xFFFFFFFF; 不会将所有位设置为“1”,它只是将整数 0xFFFFFFFF 转换为浮点表示(完全可以表示,但会损失一些精度)。

【讨论】:

    【解决方案2】:

    正如手册所说,_mm_cmpgt_ps(实际上是带有特定比较谓词的cmpps),

    对源操作数中的压缩单精度浮点值执行 SIMD 比较(第二个 操作数)和目标操作数(第一个操作数)并将比较结果返回到目标 操作数。比较谓词操作数(第三个操作数)指定对每个执行的比较类型 压缩值对。 每次比较的结果是全1(比较为真)或全为双字掩码 0s(比较错误)。比较时忽略零符号,因此 –0.0 等于 +0.0。

    (强调)

    “全 1”,或十六进制的 0xFFFFFFFF(因为它是每个元素 32 位),设置了符号位(因此有正当理由在此数字之前打印 - 符号)由于指数全为 1 且有效数不为零,因此它也是一个 NaN。 NaN-ness 通常不是很相关,这个结果的主要用途是作为按位运算中的掩码(例如_mm_and_ps_mm_blendv_ps 等),它不关心 NaN 的特殊语义。

    【讨论】:

    • 当我尝试比较 0xFFFFFFFF 和 data[0](-nan 值)时,似乎 0xFFFFFFFF 的行为与 -nan 不同。这可能是因为旗帜吗?我把上面的代码贴出来了。
    • @Cppplus1 是的,您应该遵循 Sneftels 的建议并以某种整数形式获得结果。浮点数的行为很有趣,尤其是不等于自身的 NaN。
    【解决方案3】:

    首先,不存在“否定nan”之类的东西。根据定义,nan 不是数字。你不能否定它。 -nannan 是一回事。

    没有完全符合标准的方法来获取由浮点值组成的底层位,但最接近的是memcpy。只需从指向floatdouble 的指针复制到指向同等大小的无符号整数类型的指针,然后在std::hex 处于活动状态时打印它。

    【讨论】:

    • 但是我有一个苹果和一个番茄,当我把它们加在一起时,我得到了香蕉。
    猜你喜欢
    • 1970-01-01
    • 2021-12-22
    • 2010-12-16
    • 2018-06-21
    • 2012-03-24
    相关资源
    最近更新 更多