3

I have some natural big number in double. I need to get 30 rightmost bits of it (of integral part). If it was integer the operation was:

var & 0x3FFFFFFF

I can implement some functions for the purpose, but I need some simple solution. Is there one?

*edit:

All the answers doesn't work for me. I'll try to explain: for example I have double x = 9362446620820194.0000, 30 rightmost bits of integral part of that number is the number 957350626.

I could use uint64_t instead of double, but I need support for 32 bit systems.

p.s. I mean simple binary number representation, not the machine (memory)

nik
  • 435
  • 1
  • 6
  • 14
  • 2
    The 30 rightmost bits of what? The significand? That will be some part of a scaled log base 2 value. What about the exponent and the sign bit? – talonmies Mar 11 '12 at 12:30
  • They only don't work because it seems you don't understand what it is you are asking for. You might start by reading [this link](http://en.wikipedia.org/wiki/Double-precision_floating-point_format#IEEE_754_double-precision_binary_floating-point_format:_binary64) on IEEE-754 binary 64 format. – talonmies Mar 11 '12 at 14:32
  • 2
    You can use `uint64_t` on 32 bit systems. – interjay Mar 11 '12 at 14:45
  • talonmies, Ok, in the question I mean the actual binary number representation, not machine (memory) representaion. If the double x = 15.00000 and I need 2 rightmost bits of it I mean the repr. of number (of integral part) is 1111 in binary and i need here 11 -> 3. – nik Mar 11 '12 at 14:45
  • If I can use uint64_t, so it is the solution for me. But could you explain for, how could I use uint64_t on 32 bit systems? Just for understanding. – nik Mar 11 '12 at 14:47

2 Answers2

2

Assuming 8-bit unsigned char:

unsigned char const *p = (unsigned char const *)&var;
long rightmost30 = (p[sizeof(double) - 4] & 0x3F) << 24
                 |  p[sizeof(double) - 3] << 16
                 |  p[sizeof(double) - 2] << 8
                 |  p[sizeof(double) - 1];

Though really, you should have a look at frexp and related functions.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • This will only work on big-endian systems, since you assume that the rightmost bits are always in the last bytes. – interjay Mar 11 '12 at 12:41
  • @interjay: I just assumed the OP meant the rightmost bits in the memory representation, since otherwise the operation doesn't make much sense for floating point types. – Fred Foo Mar 11 '12 at 12:57
  • 1
    I think it makes more sense to look at the rightmost bits of the format defined by IEEE-754, which would correspond to the rightmost bits of the significand. This would be stored in the first bytes in little-endian architectures. Of course, we won't know what the OP actually needs unless he tells us, and since he won't answer requests for clarification I'm voting to close this. – interjay Mar 11 '12 at 13:53
0

The casting hack:

float var = 0.2987647892;
uint32_t bit_repr = *(uint32_t *)&var;
uint32_t masked = bit_repr & 0x3FFFFFFF;
  • 2
    I think this violates the strict aliasing rule and causes undefined behavior. – Fred Foo Mar 11 '12 at 12:29
  • Even wanting to extract bits from a float is undefined IMHO, as you can't know what implementation the compiler uses... –  Mar 11 '12 at 12:52
  • gettings bits from a float gives *implement-defined* behavior, not UB. – Fred Foo Mar 11 '12 at 12:57