Как получить шестнадцатеричное значение -nan - PullRequest
0 голосов
/ 20 мая 2018

Я пишу некоторый код в Intel Intrinsics и сделал это:

#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];

Я пытаюсь получить шестнадцатеричное значение «true» в 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?

Ответы [ 3 ]

0 голосов
/ 20 мая 2018

Как сказано в руководстве, _mm_cmpgt_ps (что на самом деле cmpps с определенным предикатом сравнения),

Выполняет сравнение SIMD упакованных значений с плавающей запятой одинарной точности висходный операнд (второй операнд) и целевой операнд (первый операнд) и возвращает результаты сравнения в целевой операнд.Операнд предиката сравнения (третий операнд) указывает тип сравнения, выполняемый для каждой из пар упакованных значений. Результатом каждого сравнения является маска двойного слова со всеми 1с (сравнение истинно) или со всеми 0 (сравнение ложно). Знак ноль игнорируется для сравнений, так что –0.0 равно + 0.0.

(выделение добавлено)

"Все 1 с" или 0xFFFFFFFF в шестнадцатеричном формате (так как это 32 бита на элемент), установлен бит знака (поэтому есть законная причина для печатизнак - перед любым другим числом, которым может быть это число), и поскольку показатель степени - все единицы, а значение - не ноль, он также является NaN.Обычно NaN-сущность не очень актуальна, главное предназначение этого результата - маска в побитовых операциях (например, _mm_and_ps, _mm_blendv_ps и т. Д.), Которые не заботятся о специальной семантике NaN.

0 голосов
/ 20 мая 2018

В соответствии со спецификацией 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;
}

На машине с прямым порядком байтов будетвыведите что-то вроде:

00 00 c0 ff

PS float f = 0xFFFFFFFF; не установит все биты в «1», оно просто преобразует целое число 0xFFFFFFFF в представление с плавающей запятой (идеально представимое с некоторымипотеря точности).

0 голосов
/ 20 мая 2018

Прежде всего, не существует такого понятия, как «отрицательный nan».nan по определению не число.Вы не можете отрицать это.-nan - это то же самое, что и nan.

Не существует точно совместимого со стандартами способа получить базовые биты, содержащиеся в значении с плавающей запятой, но самый близкий - memcpy.Просто скопируйте указатель на float или double на указатель на целочисленный тип без знака эквивалентного размера, а затем напечатайте его с активным std::hex.

...