Вопрос

Есть ли простой способ определить знак номера плавающей запятой?

Я экспериментировал и придумал это:

#include <iostream>

int main(int argc, char** argv)
{
 union
 {
  float f;
  char c[4];
 };

 f = -0.0f;
 std::cout << (c[3] & 0x10000000) << "\n";

 std::cin.ignore();
 std::cin.get();
 return 0;
}

где (C [3] & 0x10000000) дает значение> 0 для отрицательного числа, но я думаю, что это требует от меня допущения, которые:

  • Байты машины 8 бит большие
  • Номер точки поплавка составляет 4 байта?
  • Машина наиболее значимой бит - это левый бит (целевость?)

Пожалуйста, поправьте меня, если кто-либо из этих предположений не прав или если я пропустил.

Это было полезно?

Решение

Предполагая, что это действительная плавающая точка (а не, например, NAN):

float f;
bool is_negative = f < 0;

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

Другие советы

Пытаться

float s = copysign(1, f);

от <math.h>

Еще одна полезная вещь может быть #including <ieee754.h>, Если это доступно в вашей системе / компилятере.

Используйте находку () из Math.h.

1) SIZEOF (INT) не имеет ничего общего с этим.

2) предполагая char_bit == 8, да.

3) нам нужен MSB для этого, но эндианс затрагивает только порядок байта, а не поручить порядок, поэтому то, что нам нужно проверить, c[0]&0x80 для большой эндианты или c[3]&0x80 Для мало, так было бы лучше декларировать союз с uint32_t и проверка с 0x80000000.

У этого трюка имеет смысл только для несовестных операндов памяти. Делать это на float Значение, которое находится в регистре XMM или X87, будет медленнее, чем прямой подход. Кроме того, он не относится к специальным значениям, таким как NAN или INF.

Google Формат с плавающей точкой для вашей системы. Многие используют IEEE 754, и в данных для изучения данных есть определенный знак. 1 отрицательный 0 положительный. Другие форматы имеют что-то подобное, а так легко изучить.

Примечание, пытаясь заставить компилятор точно дать вам номер, который вы хотите с жестким заданием, такими как F = -0.0f; не может работать. Не имеет ничего общего с форматом с плавающей точкой, но связано с анализатором и библиотекой C / C ++, используемой компилятором. Создание минус ноль может или не может быть таким тривиальным в целом.

Я получил это от http://www.cs.uaf.edu/2008/fall/cs441/lecture/10_07_float.html.попробуй это:

/* IEEE floating-point number's bits:  sign  exponent   mantissa */
struct float_bits {
    unsigned int fraction:23; /**< Value is binary 1.fraction ("mantissa") */
    unsigned int exp:8; /**< Value is 2^(exp-127) */
    unsigned int sign:1; /**< 0 for positive, 1 for negative */
};

/* A union is a struct where all the fields *overlap* each other */
union float_dissector {
    float f;
    struct float_bits b;
};

int main() {
    union float_dissector s;
    s.f = 16;
    printf("float %f  sign %u  exp %d  fraction %u",s.f, s.b.sign,((int)s.b.exp - 127),s.b.fraction);
    return 0;
}

Приходя к этому поздно, но я подумал о другом подходе.

Если вы знаете, что ваша система использует формат с плавающей точкой IEEE754, но не насколько велики типы плавающих точек относятся к целочисленным типам, вы могли бы сделать что-то подобное:

bool isFloatIEEE754Negative(float f)
{
    float d = f;
    if (sizeof(float)==sizeof(unsigned short int)) {
        return (*(unsigned short int *)(&d) >> (sizeof(unsigned short int)*CHAR_BIT - 1) == 1);
    }
    else if (sizeof(float)==sizeof(unsigned int)) {
        return (*(unsigned int *)(&d) >> (sizeof(unsigned int)*CHAR_BIT - 1) == 1);
    }
    else if (sizeof(float)==sizeof(unsigned long)) {
        return (*(unsigned long *)(&d) >> (sizeof(unsigned long)*CHAR_BIT - 1) == 1);
    }
    else if (sizeof(float)==sizeof(unsigned char)) {
        return (*(unsigned char *)(&d) >> (sizeof(unsigned char)*CHAR_BIT - 1) == 1);
    }
    else if (sizeof(float)==sizeof(unsigned long long)) {
        return (*(unsigned long long *)(&d) >> (sizeof(unsigned long long)*CHAR_BIT - 1) == 1);
    }
    return false; // Should never get here if you've covered all the potential types!
}

По сути, вы относитесь к байтам в своем плаву как целочисленный тип без знака, а затем правый смещенный все, кроме одного из битов (подписанный бит) из существования. '>>' работает независимо от эндин, поэтому это обходит этот вопрос.

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

#define FLOAT_EQUIV_AS_UINT unsigned int // or whatever it is

bool isFloatIEEE754Negative(float f)
{
    float d = f;
    return (*(FLOAT_EQUIV_AS_UINT *)(&d) >> (sizeof(FLOAT_EQUIV_AS_UINT)*CHAR_BIT - 1) == 1);
}

Это работало в моих тестовых системах; Кто-нибудь видят какие-либо предостережения или упущенные из виду «чтчас»?

Почему бы нет if (f < 0.0)?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top