representar que punto para numero notación normalizado normalizada mantisa informatica flotante exponente estandar ejemplos coma c++ floating-point signedness

c++ - que - Signo de un número de coma flotante



punto flotante plc (8)

¿Hay alguna forma fácil de determinar el signo de un número de coma flotante?

Experimenté y se me ocurrió esto:

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

donde (c [3] y 0x10000000) da un valor> 0 para un número negativo, pero creo que esto requiere que haga las suposiciones de que:

  • Los bytes de la máquina son 8 bits grandes
  • un número de punto flotante tiene 4 bytes de tamaño?
  • el bit más significativo de la máquina es el bit más a la izquierda (¿endianness?)

Por favor, corrígeme si alguna de esas suposiciones es incorrecta o si me he perdido alguna.


¿Por qué no if (f < 0.0) ?


1) sizeof (int) no tiene nada que ver con eso.

2) suponiendo CHAR_BIT == 8, sí.

3) necesitamos MSB para eso, pero la endianidad solo afecta el orden de bytes, no el orden de bits, por lo que el bit que necesitamos verificar es c[0]&0x80 para big endianness, o c[3]&0x80 para poco, así que sería mejor declarar la unión con uint32_t y verificar con 0x80000000.

Este truco solo tiene sentido para los operandos de memoria no especiales. Hacerlo a un valor float que esté en XMM o registro x87 será más lento que el enfoque directo. Además, no trata los valores especiales como NaN o INF.


Suponiendo que es un número de punto flotante válido (y no, por ejemplo, NaN):

float f; bool is_negative = f < 0;

Se deja como ejercicio al lector averiguar cómo probar si un número de punto flotante es positivo.


Tratar

float s = copysign(1, f);

de <math.h>

Otra cosa útil puede ser #including <ieee754.h> , si está disponible en su sistema / compilador.


Use signbit () desde math.h.


google el formato de punto flotante para su sistema. Muchos usan IEEE 754 y hay un bit de signo específico en los datos para examinar. 1 es negativo 0 es positivo. Otros formatos tienen algo similar y son fáciles de examinar.

Tenga en cuenta que intenta obtener el compilador para darle exactamente el número que desea con una asignación codificada como f = -0.0F; puede que no funcione. no tiene nada que ver con el formato de coma flotante, pero tiene que ver con el analizador y la biblioteca C / C ++ utilizada por el compilador. Generar un cero negativo puede o no ser tan trivial en general.


Lo tengo de http://www.cs.uaf.edu/2008/fall/cs441/lecture/10_07_float.html prueba esto:

/* 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; }


Llegando a esto tarde, pero pensé en otro enfoque.

Si sabe que su sistema usa el formato de punto flotante IEEE754, pero no el tamaño de los tipos de coma flotante con respecto a los tipos enteros, podría hacer algo como esto:

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! }

Básicamente, tratas los bytes de tu float como un tipo de entero sin signo, luego haces clic con el botón derecho en todos menos en uno de los bits (el bit de signo) y desaparecen. ''>>'' funciona independientemente de endianidad por lo que esto pasa por alto ese problema.

Si es posible determinar la preejecución cuyo tipo de enteros sin signo tiene la misma longitud que el tipo de coma flotante, podría abreviar esto:

#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); }

Esto funcionó en mis sistemas de prueba; ¿Alguien ve alguna advertencia o pasa por alto ''gotchas''?