Сравнение поплавков в их битовых представлениях - PullRequest
4 голосов
/ 06 апреля 2010

Скажем, я хочу функцию, которая принимает два числа с плавающей точкой (x и y), и я хочу сравнить их, используя не их float представление, а скорее их побитовое представление как 32-битное unsigned int.То есть число типа -495.5 имеет битовое представление 0b11000011111001011100000000000000 или 0xC3E5C000 как float, и у меня есть unsigned int с таким же битовым представлением (соответствует десятичному значению 3286614016, которое я надеваювсе равно)Есть ли какой-нибудь простой способ для меня выполнить операцию типа <= на этих поплавках, используя только информацию, содержащуюся в их соответствующих unsigned int аналогах?

Ответы [ 4 ]

4 голосов
/ 06 апреля 2010

Вы должны выполнить сравнение со знаком, если не уверены, что все исходные значения были положительными. Вы должны использовать целочисленный тип того же размера, что и исходный тип с плавающей запятой. Каждый чип может иметь свой внутренний формат, поэтому сравнение значений из разных чипов с целыми числами, скорее всего, даст неверные результаты.

Большинство форматов с плавающей точкой выглядят примерно так: sxxxmmmm

s является знаковым битом
xxx - это показатель степени
mmmm это мантисса

Тогда представленное значение будет примерно таким: 1mmm << (xxx-k)

1mmm, поскольку имеется подразумеваемый ведущий бит 1, если значение не равно нулю.

Если xxx < k, то это будет сдвиг вправо. k близко, но не равно половине наибольшего значения, которое может быть выражено xxx. Настраивается на размер мантиссы.

Все это говорит о том, что без учета NaN сравнение значений с плавающей запятой как целых чисел со знаком одинакового размера даст значимые результаты. Они разработаны таким образом, чтобы сравнения с плавающей запятой были не более дорогостоящими, чем целочисленные сравнения. Существуют оптимизации компилятора, чтобы отключить NaN проверки, чтобы сравнения представляли собой прямые целочисленные сравнения, если формат чипа с плавающей запятой это поддерживает.

Как целое число, NaN больше бесконечности, больше конечных значений. Если вы попытаетесь сравнить без знака, все отрицательные значения будут больше положительных значений, так же как целые числа со знаком, приведенные к беззнаковому.

3 голосов
/ 06 апреля 2010

Если вы действительно не заботитесь о том, что дает конверсия, это не так уж сложно. Но результаты чрезвычайно непереносимы, и вы почти наверняка не получите заказ, который будет полностью соответствовать тому, что вы получите, сравнив поплавки напрямую.

typedef unsigned int TypeWithSameSizeAsFloat; //Fix this for your platform

bool compare1(float one, float two)
    union Convert {
        float f;
        TypeWithSameSizeAsFloat i;
    }
    Convert lhs, rhs;
    lhs.f = one;
    rhs.f = two;
    return lhs.i < rhs.i;
}

bool compare2(float one, float two) {
    return reinterpret_cast<TypeWithSameSizeAsFloat&>(one) 
         < reinterpret_cast<TypeWithSameSizeAsFloat&>(two);
}

Просто поймите предостережения и тщательно выберите ваш второй тип. Во всяком случае, это почти ничего не стоящее упражнение.

3 голосов
/ 06 апреля 2010

Одним словом, нет. IEEE 754 может разрешать некоторые виды хаков, подобных этому, но они не работают все время и обрабатывают все случаи, и некоторые платформы не используют этот стандарт с плавающей запятой (например, удваивается на x87 с внутренней точностью 80 бит).

Если вы делаете это по соображениям производительности, я настоятельно рекомендую вам пересмотреть - если быстрее использовать целочисленное сравнение, компилятор, вероятно, сделает это за вас, а если нет, вы заплатите за преобразование с плавающей точкой в ​​int. несколько раз, когда возможно простое сравнение без перемещения чисел из регистров.

2 голосов
/ 06 апреля 2010

Может быть, я неправильно понимаю вопрос, но я полагаю, вы могли бы сделать это:

bool compare(float a, float b)
{
    return *((unsigned int*)&a) < *((unsigned int*)&b);
}

Но это предполагает все виды вещей, а также ставит вопрос о том, почему вы хотите сравнить побитовые представления двух чисел с плавающей запятой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...