Estoy trabajando en un programa que necesita para convertir un número de 32 bits en un número decimal.

El número que tengo de entrada es un número de 32 bits representado como número de punto flotante. El primer bit es el signo, el próximo 8 bits son el exponente, y el otro de 23 bits de mantisa. Estoy trabajando el programa en C. en la entrada, me sale ese número como un char[] matriz, y después de que me estoy haciendo un nuevo int[] matriz donde puedo almacenar el signo , el exponente y la mantisa. Pero, tengo un problema con la mantisa cuando estoy tratando de guardarlo en algún tipo de datos, porque necesito usar la mantisa como un número, no como una matriz: formula=sign*(1+0.mantissa)*2^(exponent-127).

Aquí es el código que uso para almacenar la mantisa, pero aún así el programa me pone mal de los resultados:

double oMantissa=0;
int counter=0;
for(counter=0;counter<23;counter++)
{
    if(mantissa[counter]==1)
    {
        oMantissa+=mantissa[counter]*pow(10,-counter);
    }
}

mantissa[] es un int matriz en la que ya me he convertido la mantisa de un char matriz. Cuando llego el valor de formula, tiene que ser un número binario, y tengo que convertirlo a decimal, así que voy a obtener el valor del número. Me pueden ayudar con el almacenamiento de los 23 bits de la mantisa? Y, yo no debo usar funciones como strtoul que convertir el número de 32 bits directamente en binario. Tengo que usar formula.

  • ¿Qué es un «número decimal»? Que no tiene sentido. (Tampoco «número de 32 bits» para que la materia.)
  • ¿Te refieres a preguntar: quiero formatear un número de punto flotante, dado que en 32 bits IEEE754 representación, como un número decimal representación de cadena?» (Que es bastante peludo, por el camino. Echa un vistazo este artículo.)
  • ¿Por qué no «número decimal» de sentido?no tenemos binario,decimal,octal y hexadecimal de sistemas?Estoy tan confundido.¿Puede explicar plz?
  • Es el número de dedos de la mano decimal, binario o octal? Se puede ver, no tiene sentido. Los números son sólo números.
  • Me refiero a las representaciones…..decimal,binario,octal,…Estoy ahora en mi contraste entre representations vs numbers.Eso es lo que significa la derecha?
  • Bueno, algo así. Pero es una gran distinción. Usted nunca debe ser casual al respecto. Los números fundamentales, concepto universal. Las representaciones son sólo arbitrariamente elegido convenciones.
  • consulte este enlace: en.wikipedia.org/wiki/Single_precision_floating-point_format. Tengo 32 dígitos de número en la entrada. Es en el estándar IEEE 754, así que cuando me convertirlo puedo obtener década el número, pero decimal. Por ejemplo: Entrada: 010000101100010010000000000000000 de Salida: 98.25
  • Es esta tarea? Por qué no se pueden utilizar funciones de la biblioteca?
  • Es una tarea, y se dice que no debo utilizar funciones, como la de este código, serán revisados por mis profesores en la facultad. Así que, yo no puede usar ninguna de las funciones de la biblioteca
  • jeje haciendo muuuy duro. acaba de tomar mantisa y cambiarlo por exponentt, no necesita ningún tipo de matrices, para llegar a flotar como int hacer esto: [ float f; DWORD d=((DWORD*)(&f))[0]; ] esta copia de a poco todo float f a DWORD d (se puede usar unsigned int,o int o __int32 lugar). después de esto, usted puede usar << >> & | operadores que hace las cosas fáciles. por ejemplo [ bool signo=d&0x80000000; ] por supuesto, usted no puede obtener el valor int si el exponente es <0 o si cambio de perder bits. No te olvides de añadir 1 antes de la mantisa después de exp extracción. por supuesto, si la entrada debe ser char[] que no tienes elección

InformationsquelleAutor | 2013-04-23

2 Comentarios

  1. 2

    Que parte de el código de abajo, fue duro para obtener el derecho dado todas las fórmulas y números de muestra y una calculadora?

    #include <stdio.h>
    #include <limits.h>
    #if UINT_MAX >= 0xFFFFFFFF
    typedef unsigned uint32;
    #else
    typedef unsigned long uint32;
    #endif
    #define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
    //Ensure uint32 is exactly 32-bit
    C_ASSERT(sizeof(uint32) * CHAR_BIT == 32);
    //Ensure float has the same number of bits as uint32, 32
    C_ASSERT(sizeof(uint32) == sizeof(float));
    double Ieee754SingleDigits2DoubleCheat(const char s[32])
    {
    uint32 v;
    float f;
    unsigned i;
    char *p1 = (char*)&v, *p2 = (char*)&f;
    //Collect binary digits into an integer variable
    v = 0;
    for (i = 0; i < 32; i++)
    v = (v << 1) + (s[i] - '0');
    //Copy the bits from the integer variable to a float variable
    for (i = 0; i < sizeof(f); i++)
    *p2++ = *p1++;
    return f;
    }
    double Ieee754SingleDigits2DoubleNoCheat(const char s[32])
    {
    double f;
    int sign, exp;
    uint32 mant;
    int i;
    //Do you really need strto*() here?
    sign = s[0] - '0';
    //Do you really need strto*() or pow() here?
    exp = 0;
    for (i = 1; i <= 8; i++)
    exp = exp * 2 + (s[i] - '0');
    //Remove the exponent bias
    exp -= 127;
    //Should really check for +/-Infinity and NaNs here
    if (exp > -127)
    {
    //Normal(ized) numbers
    mant = 1; //The implicit "1."
    //Account for "1." being in bit position 23 instead of bit position 0
    exp -= 23;
    }
    else
    {
    //Subnormal numbers
    mant = 0; //No implicit "1."
    exp = -126; //See your IEEE-54 formulas
    //Account for ".1" being in bit position 22 instead of bit position -1
    exp -= 23;
    }
    //Or do you really need strto*() or pow() here?
    for (i = 9; i <= 31; i++)
    mant = mant * 2 + (s[i] - '0');
    f = mant;
    //Do you really need pow() here?
    while (exp > 0)
    f *= 2, exp--;
    //Or here?
    while (exp < 0)
    f /= 2, exp++;
    if (sign)
    f = -f;
    return f;
    }
    int main(void)
    {
    printf("%+g\n", Ieee754SingleDigits2DoubleCheat("110000101100010010000000000000000"));
    printf("%+g\n", Ieee754SingleDigits2DoubleNoCheat("010000101100010010000000000000000"));
    printf("%+g\n", Ieee754SingleDigits2DoubleCheat("000000000100000000000000000000000"));
    printf("%+g\n", Ieee754SingleDigits2DoubleNoCheat("100000000100000000000000000000000"));
    printf("%+g\n", Ieee754SingleDigits2DoubleCheat("000000000000000000000000000000000"));
    printf("%+g\n", Ieee754SingleDigits2DoubleNoCheat("000000000000000000000000000000000"));
    return 0;
    }

    De salida (ideone):

    -98.25
    +98.25
    +5.87747e-39
    -5.87747e-39
    +0
    +0
    • Aparte de la INF/NAN (que anotó), se ve a prueba de balas. Podría haber utilizado constantes con nombre en lugar de desnudo números de magia, pero esta respuesta es mucho más de lo que merecía. BTW: Como el [(expr)?1:-1] truco. +1
  2. 1

    No hace mucho, tuve la oportunidad de escribir una pieza similar de código que usted, y otros, puede encontrar útil. Toma una cadena de caracteres que representa un número de punto flotante como el primer argumento para el programa y convierte la cadena a su IEEE-754 Único Punto Flotante de Precisión representación junto con su equivalente valor entero. Echa un vistazo y que me haga saber si usted tiene alguna pregunta.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <errno.h>
    #if defined(__LP64__) || defined(_LP64)
    # define BUILD_64   1
    #endif
    /* constants for word and double-word size */
    #define WDSZ 64
    #define DWSZ 128
    inline int getmsb (unsigned long x);
    char *fmt_binstr (unsigned long n, unsigned char sz, unsigned char szs, char sep);
    char *binstr (unsigned long n);
    char *fpfrc_bin (float fvalue);
    void show_fltmem (float f);
    void show_ieee754str (char *s);
    void show_ieee754 (float f);
    float xstrtof (char *str);
    char *form_ieee754SPstr (int sign, char *exp, char *dec, char *frac);
    int main (int argc, char** argv) {
    if (argc < 2) {
    fprintf (stderr, "error: insufficient input. Usage: %s float\n", argv[0]);
    return 1;
    }
    char *dp = strchr (argv[1], '.');   /* pointer to decimal point */
    int dec = atoi (argv[1]);           /* integer of decimal part  */
    int frc = (dp) ? atoi (dp + 1) : 0; /* integer of fraction part */
    /* output string input values  */
    printf ("\nString Values:\n");
    printf (" string   : %s\n whole    : %d\n fraction : %d\n\n", argv[1], dec, frc);
    float fvalue = xstrtof (argv[1]);
    float ffrc = fvalue - dec;
    int signbit = (fvalue >= 0) ? 0 : 1;
    /* output float input values   */
    printf ("Float Values:\n");
    printf (" decimal  : %d\n fraction : %f\n\n", dec, ffrc);
    char *fstring = fpfrc_bin (fvalue);         /* fraction part in binary  */
    char *bs = binstr ((unsigned long) dec);    /* decimal part in binary   */
    /* output binary values decimal part/fraction part */
    printf ("Binary Values:\n");
    printf (" decimal  : %s\n fraction : %s\n sign bit : %d\n\n", bs, fstring, signbit);
    /* quick hack of exp bias, biased value, conversion to binary   */
    int bias = (int) strlen (bs) - 1;
    int biasexp = 127+bias;
    char *binexp = binstr ((unsigned long) biasexp);
    /* output summary of biased IEEE-754 exponent */
    printf ("Normalization for biased exponent:\n");
    printf ("\n %s.%s  =>  %s.%s%s\n\n", bs, fstring, "1", (bs+1), fstring);
    printf ("     exponent bias: %d\n unbiased exponent: 127\n", bias);
    printf (" __________________+____\n\n");
    printf ("   biased exponent: %3d\n   binary exponent: %s\n\n", biasexp, binexp);
    /* output summary of IEEE-754 mantissa */
    printf ("Conversion to 'hidden bit' format to form mantissa:\n\n");
    printf (" %s.%s%s  =>  %s%s\n\n", "1", (bs+1), fstring, (bs+1), fstring);
    /* form IEEE-754 binary representation from values computed */
    char *ieee754str = form_ieee754SPstr (signbit, binexp, bs, fstring);
    /* output formatted complete IEEE-754 binary - from computed values above */
    printf ("IEEE-754 Single Precision Floating Point Representation (caclulated value)\n\n");
    show_ieee754str (ieee754str);
    /* output formatted complete IEEE-754 binary - from float value in memory */
    printf ("IEEE-754 Single Precision Floating Point Representation (memory value)\n\n");
    show_ieee754 (fvalue);
    /* output float, binary and integer equivalent */
    show_fltmem (fvalue);
    if (bs) free (bs);
    if (binexp) free (binexp);
    if (ieee754str) free (ieee754str);
    return 0;
    }
    /** single-precision float in memory
    *  output the float, equivalent unsigned int, and
    *  binary representation of the number in memory
    */
    void show_fltmem (float f)
    {
    unsigned int i = *(unsigned int *)&f;
    printf ("\nRepresentations of float value in memory:\n\n");
    printf ("    The float value entered : %f\n\n", f);
    printf ("    binary value in memory  : %s\n\n", fmt_binstr (i, 32, 8, '-'));
    printf ("    bits as unsigned int    : %u\n\n", i);
    }
    /** most significant bit.
    *  return the 0-based most significant bit for any
    *  unsigned value using the bit-scan-right assembly
    *  directive.
    */
    inline int getmsb (unsigned long x)
    {
    #ifdef BUILD_64
    asm ("bsrq %0, %0" : "=r" (x) : "0" (x));
    #else
    asm ("bsr %0, %0" : "=r" (x) : "0" (x));
    #endif
    return x;
    }
    /** returns pointer to formatted binary representation of 'n' zero padded to 'sz'.
    *  returns pointer to string contianing formatted binary representation of
    *  unsigned 64-bit (or less ) value zero padded to 'sz' digits with char
    *  'sep' placed every 'szs' digits. (e.g. 10001010 -> 1000-1010).
    */
    char *fmt_binstr (unsigned long n, unsigned char sz, unsigned char szs, char sep) {
    static char s[DWSZ + 1] = {0};
    char *p = s + DWSZ;
    unsigned char i;
    for (i = 0; i < sz; i++) {
    p--;
    if (i > 0 && szs > 0 && i % szs == 0)
    *p-- = sep;
    *p = (n >> i & 1) ? '1' : '0';
    }
    return p;
    }
    /** returns an allocated string containing unpadded binary
    *  representation of the integer value 'n'. This value must
    *  be assigned to a pointer and freed to prevent leaks.
    */
    char *binstr (unsigned long n)
    {
    unsigned char msb = getmsb (n);
    char *s = calloc (msb + 2, sizeof *s);
    char *p = s + msb;
    unsigned char i;
    for (i = 0; i < msb+1; i++) {
    *p-- = (n >> i & 1) ? '1' : '0';
    }
    return s;
    }
    /** return string containing binary representation of fraction
    *  The function takes a float as an argument and computes the
    *  binary representation of the fractional part of the float,
    *  On success, the function returns a null-terminated string
    *  containing the binary value, or NULL otherwise. MAXD of 24
    *  (23 + null-term) for Single-Precision mantissa, 53
    *  (52 + null-term) for Double-Precision mantissa.
    */
    char *fpfrc_bin (float fvalue)
    {
    float fv = fvalue - (int)fvalue;
    int MAXD = 24;
    char *fvs = calloc (MAXD, sizeof *fvs);
    if (!fvs) {
    fprintf (stderr, "%s()_error: allocation failed.\n", __func__);
    return NULL;
    }
    char *p = fvs;
    unsigned char it = 0;
    while (fv > 0 && it < MAXD)
    {
    fv = fv * 2.0;
    *p++ = ((int)fv) ? '1' : '0';
    fv = ((int)fv >= 1) ? fv - 1.0 : fv;
    it++;
    }
    return fvs;
    }
    /** formatted output of ieee-754 representation of float from binary string.
    */
    void show_ieee754str (char *s)
    {
    printf (" ");
    while (*s)
    printf (" %c", *s++);
    printf ("\n");
    printf (" |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|\n");
    printf (" |s|      exp      |                  mantissa                   |\n\n");
    }
    /** formatted output of ieee-754 representation of float from stored value.
    */
    void show_ieee754 (float f)
    {
    printf ("  ");
    int i = 32;
    while (i) {
    i--;
    printf ("%d ", ((*(int *)&f >> i) & 0x1));
    }
    printf ("\n");
    printf (" |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|\n");
    printf (" |s|      exp      |                  mantissa                   |\n\n");
    }
    /** string to float with error checking. */
    float xstrtof (char *str)
    {
    char *endptr = NULL;
    errno = 0;
    float val = strtof (str, &endptr);
    /* Check for various possible errors */
    if ((errno == ERANGE && (val == HUGE_VALF || val == HUGE_VALL)) ||
    (errno != 0 && val == 0)) {
    perror ("strtof");
    exit (EXIT_FAILURE);
    }
    if (endptr == str) {
    fprintf (stderr, "No digits were found\n");
    exit (EXIT_FAILURE);
    }
    return val;
    }
    /** form IEEE-754 binary representation from computed  values for the
    *  sign bit, biased exponent binary string, decimal binary string, and
    *  fractional binary string, forming the 23-bit mantissa from the decimal
    *  and fractional strings, filling with '0' as needed. An allocated
    *  string containing the IEEE-754 Single-Precision representation is
    *  returned.
    */
    char *form_ieee754SPstr (int sign, char *exp, char *dec, char *frac)
    {
    char *str = calloc (33, sizeof *str);
    char *p = str + 1;
    char *sp = dec + 1;                         /* leading 1 - hidden bit   */
    size_t fsl = strlen (frac);                 /* length of fractional str */
    size_t manbits = fsl + strlen (sp);         /* available mantissa bits  */
    size_t mdiff = 23 - manbits;                /* diff from required 23    */
    *str = (sign == 0) ? '0' : '1';             /* set sign bit in string   */
    memcpy (p, exp, 8);                         /* set biased exponent      */
    p += 8;
    while (*sp) { *p = *sp++; p++; };           /* mantissa - decimal bits  */
    if (manbits < 23)                           /* test < 23 bits available */
    {
    memcpy (p, frac, fsl);                  /* copy fractional bits     */
    p += fsl;                               /* increment pointer        */
    register size_t it = 0;
    if (mdiff > 0)                          /* fill remaining mantissa  */
    for (it = 0; it < mdiff; it++)
    {
    *p = '0';
    p++;
    }
    }
    else
    {
    memcpy (p, frac, 23);                   /* fill mantissa w/23 bits  */
    }
    return str;
    }

    Ejemplo De Uso/Salida

    $ ./bin/ieee754cvt 123.456
    String Values:
    string   : 123.456
    whole    : 123
    fraction : 456
    Float Values:
    decimal  : 123
    fraction : 0.456001
    Binary Values:
    decimal  : 1111011
    fraction : 01110100101111001
    sign bit : 0
    Normalization for biased exponent:
    1111011.01110100101111001  =>  1.11101101110100101111001
    exponent bias: 6
    unbiased exponent: 127
    __________________+____
    biased exponent: 133
    binary exponent: 10000101
    Conversion to 'hidden bit' format to form mantissa:
    1.11101101110100101111001  =>  11101101110100101111001
    IEEE-754 Single Precision Floating Point Representation (caclulated value)
    0 1 0 0 0 0 1 0 1 1 1 1 0 1 1 0 1 1 1 0 1 0 0 1 0 1 1 1 1 0 0 1
    |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
    |s|      exp      |                  mantissa                   |
    IEEE-754 Single Precision Floating Point Representation (memory value)
    0 1 0 0 0 0 1 0 1 1 1 1 0 1 1 0 1 1 1 0 1 0 0 1 0 1 1 1 1 0 0 1
    |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
    |s|      exp      |                  mantissa                   |
    Representations of float value in memory:
    The float value entered : 123.456001
    binary value in memory  : 01000010-11110110-11101001-01111001
    bits as unsigned int    : 1123477881

Dejar respuesta

Please enter your comment!
Please enter your name here