C++ Casting Help

Discussion in 'Techforge' started by Spider, Nov 13, 2009.

  1. Spider

    Spider Splat

    Joined:
    Jun 4, 2004
    Messages:
    5,233
    Ratings:
    +447
  2. Paladin

    Paladin Overjoyed Man of Liberty

    Joined:
    Mar 29, 2004
    Messages:
    50,154
    Location:
    Spacetime
    Ratings:
    +53,511
    Might the following work? (I can't test it where I'm at.)

    ...
    char *end;
    char* s = "0xFF0A003C";
    float f = strtof(s, end); // should test end for null to see if conversion was ok
    cout << f;
    ...

    see also strtod(), strtold()


    I hope that's helpful...
    • Agree Agree x 2
  3. Spider

    Spider Splat

    Joined:
    Jun 4, 2004
    Messages:
    5,233
    Ratings:
    +447
    It's not quite right, but it points me in a useful direction, I think. Thanks.
    Code:
    int main() {
        char *end;
        char* paladin_char = "0xFF0A003C";
        char* spider_char_one = "42140bb4";
        char* spider_char_two = "42141e4c";
        
        float paladin_float = strtof(paladin_char, &end);
        float spider_float_one = strtof(spider_char_one, &end);
        float spider_float_two = strtof(spider_char_two, &end);
        
        cout << paladin_char    << "\t->\t" <<  paladin_float    << "\n";
        cout << spider_char_one << "\t->\t" <<  spider_float_one << "\n";
        cout << spider_char_two << "\t->\t" <<  spider_float_two << "\n";
        return(0);
    }
    
    
    gives:
    0xFF0A003C      ->      4.27885e+09
    42140bb4        ->      42140
    42141e4c        ->      4.2141e+08
    
  4. Powaqqatsi

    Powaqqatsi Haters gonna hate.

    Joined:
    Apr 15, 2004
    Messages:
    8,388
    Ratings:
    +1,341
    Cheap way out! But that's always the best way realistically don't reinvent the wheel when you dont have to.

    However, if you want to roll your own you need to understand the spec: http://en.wikipedia.org/wiki/Single_precision

    I remember I had a similar problem back in school, had to be solved in Sparc assembly using only integer operations but the concepts can be carried over.

    Basically the idea is you use a bit mask to do a bitwise AND on the number (to zero out the leading digits you don't care about), then you shift right until you get a regular old integer for the sign, exponent, and significand portions of the number, then you can manually figure out the value.

    The same concepts are easier to apply to a string than a bunch of bits as well.

    But you should really go for paladins method unless what you are doing is a learning exercise or something
    • Agree Agree x 2
  5. Spider

    Spider Splat

    Joined:
    Jun 4, 2004
    Messages:
    5,233
    Ratings:
    +447
    Code:
    string initial_result=exec("nc -i 2 mds-4c-xx02 2103 < get_data_command | od -t xC");
    
    /////////////////////////////
    string temp_buff;
    stringstream temp_ss(initial_result);
    vector<string> temp_v;
    while (temp_ss >> temp_buff) temp_v.push_back(temp_buff);
    string trimmed_result="0x"+temp_v.at(6)+temp_v.at(7)+temp_v.at(4)+temp_v.at(5);
    /////////////////////////////
    
    
    const char *Input=trimmed_result.c_str();
    unsigned long unsigned_long = strtoul (Input,NULL,0);
    union { unsigned long ul; float f;} u;
    u.ul = unsigned_long;
    float final_result = u.f; 
    
    printf("%f\n",final_result);
    
    This works. :shrug:
    Last edited: Nov 13, 2009
    • Agree Agree x 1
  6. Spider

    Spider Splat

    Joined:
    Jun 4, 2004
    Messages:
    5,233
    Ratings:
    +447
    Hell, no. The simpler the better. I just can't get Paladin's to work, either.
  7. Paladin

    Paladin Overjoyed Man of Liberty

    Joined:
    Mar 29, 2004
    Messages:
    50,154
    Location:
    Spacetime
    Ratings:
    +53,511
    Have you verified that works?

    I'm a little rusty with union, but reinterpreting the bits of a long integer into a float doesn't seem like that should produce the right answer...

    edit: unless, of course, you knew that the hex you started with was created in the reverse operation (float -> unsigned long).
    • Agree Agree x 1
  8. Order2Chaos

    Order2Chaos Ultimate... Immortal Administrator

    Joined:
    Apr 2, 2004
    Messages:
    25,198
    Location:
    here there be dragons
    Ratings:
    +21,417
    It'll work, at least in a 32-bit runtime, even if it is slightly abusive of the type system.

    Edit, then again, I did do this once:

    //I have a bitfield bf which is a typedef'd int

    char ar[4] = *bf;
    char a = ar[0];
    char b = ar[1];
    char c = ar[2];
    char d = ar[3];

    instead of
    char a = bf >> 24;
    char b = bf >> 16;
    char c = bf >> 8;
    char d = (char)bf;
    • Agree Agree x 1
  9. Spider

    Spider Splat

    Joined:
    Jun 4, 2004
    Messages:
    5,233
    Ratings:
    +447
    It seems to work fine so far. :shrug:
  10. Spider

    Spider Splat

    Joined:
    Jun 4, 2004
    Messages:
    5,233
    Ratings:
    +447
    Of course, they're like London buses. As soon as one solution comes along, another one pops up, just to make you look stupid.

    Thanks again, guys.


    Code:
    #include <stdio.h>
    
    union ieee754 {
      int hex;
      float flt;
    };
    
    int main () {
    
      int h1 = 0x42141cd7;
      float f1 = *((float*)&h1);
    
      float f2=37.028164;
      int h2= *((int*)&f2);
    
      printf("IEEE Hex: 0x%8.8x -> Float:  %f\n", h1, f1);
      printf("IEEE Hex: 0x%8.8x <- Float:  %f\n", h2, f2);
    
      ///////////////////////////
    
      ieee754 var1;
      ieee754 var2;
    
      var1.hex = 0x42141cd7;
      var2.flt = 37.028164;
    
      printf("IEEE Hex: 0x%8.8x -> Float:  %f\n", var1.hex, var1.flt);
      printf("IEEE Hex: 0x%8.8x <- Float:  %f\n", var2.hex, var2.flt);
    
      return 0;
    }
    
  11. Order2Chaos

    Order2Chaos Ultimate... Immortal Administrator

    Joined:
    Apr 2, 2004
    Messages:
    25,198
    Location:
    here there be dragons
    Ratings:
    +21,417
    ^Either of those two are much better than the previous one, as they're 64-bit safe. This one's not 16-bit safe, but I think that'll be a rarer case unless you're doing embedded processor programming.
  12. Baba

    Baba Rep Giver

    Joined:
    Mar 29, 2004
    Messages:
    16,680
    Ratings:
    +5,373
    Anymonous union outside main would have to be declared static.
    • Agree Agree x 1
  13. Spider

    Spider Splat

    Joined:
    Jun 4, 2004
    Messages:
    5,233
    Ratings:
    +447
    Thanks, I hadn't realised that. 64-bit is a possible future danger. 16--not so much.
  14. Order2Chaos

    Order2Chaos Ultimate... Immortal Administrator

    Joined:
    Apr 2, 2004
    Messages:
    25,198
    Location:
    here there be dragons
    Ratings:
    +21,417
    ^Aye. In gcc-64, ints are 32 bits and longs are 64 bits. This is a change from the 16->32 bit transition, where both ints and longs became 32 bits from 16 bits. The other thing you can use, if your library supports it, is the u_int32/uint32/uint_32 type, which is typedefed in several #ifdef blocks so that no matter what platform you're on, you always get a 32-bit wide data type if the hardware supports it.