C / C ++ Java equivalent doubleToRawLongBits ()

In Java, Double.doubleToLongBits() is useful to use hashCode() methods.

I am trying to do the same in C ++ and write my own doubleToRawLongBits() method, since after trawling through Google I cannot find a suitable implementation.

I can get signif and exponent from std::frexp(numbr,&exp) and determine the sign, but I can not understand the use of bitwise operators to get the Java equivalent.

For example, Java Double.doubleToLongBits() returns the following for double 3.94:

4616054510065937285

Thanks for any help.

Graham

Below is the documentation copied and pasted from Double.doubleToRawLongBits ()

 ===Java Double.doubleToRawLongBits() description=== /** * Returns a representation of the specified floating-point value * according to the IEEE 754 floating-point "double * format" bit layout, preserving Not-a-Number (NaN) values. * <p> * Bit 63 (the bit that is selected by the mask * <code>0x8000000000000000L</code>) represents the sign of the * floating-point number. Bits * 62-52 (the bits that are selected by the mask * <code>0x7ff0000000000000L</code>) represent the exponent. Bits 51-0 * (the bits that are selected by the mask * <code>0x000fffffffffffffL</code>) represent the significand * (sometimes called the mantissa) of the floating-point number. * <p> * If the argument is positive infinity, the result is * <code>0x7ff0000000000000L</code>. * <p> * If the argument is negative infinity, the result is * <code>0xfff0000000000000L</code>. * <p> * If the argument is NaN, the result is the <code>long</code> * integer representing the actual NaN value. Unlike the * <code>doubleToLongBits</code> method, * <code>doubleToRawLongBits</code> does not collapse all the bit * patterns encoding a NaN to a single &quot;canonical&quot; NaN * value. * <p> * In all cases, the result is a <code>long</code> integer that, * when given to the {@link #longBitsToDouble(long)} method, will * produce a floating-point value the same as the argument to * <code>doubleToRawLongBits</code>. * * @param value a <code>double</code> precision floating-point number. * @return the bits that represent the floating-point number. * @since 1.3 */ public static native long doubleToRawLongBits(double value); 
+4
source share
3 answers
 #include <stdint.h> static inline uint64_t doubleToRawBits(double x) { uint64_t bits; memcpy(&bits, &x, sizeof bits); return bits; } 
+4
source

A simple broadcast will do:

 double d = 0.5; const unsigned char * buf = reinterpret_cast<const unsigned char *>(&d); for (unsigned int i = 0; i != sizeof(double); ++i) std::printf("The byte at position %u is 0x%02X.\n", i, buf[i]); 

Where sign and exponent bits depend on your platform and content ability. If your floats are IEE754, if the sign and exponent are in front, and if CHAR_BIT == 8 , you can try the following:

 const bool sign = buf[0] & 0x80; const int exponent = ((buf[0] & 0x7F) << 4) + (buf[1] >> 4) - 1023; 

(In C, let's say (const unsigned char *)(&d) for translation.)

Update. To create an integer with the same bits, you first need to make an integer, and then copy:

 unsigned long long int u; unsigned char * pu = reinterpret_cast<unsigned char *>(&u); std::copy(buf, buf + sizeof(double), pu); 

To do this, you need to keep in mind several things: the size of the integer must be sufficient (the static statement for sizeof(double) <= sizeof(unsigned long long int) should do the trick), and if the integer is actually larger, then you are only copying to its parts. I'm sure you can figure it out though :-) (You can use the magic of templates to create an integer of the right size if you really wanted to.)

+8
source

I like alliances for this kind of thing.

 union double_and_buffer { double d; unsigned char byte_buff[ sizeof(double) ]; } dab; dab.d = 1.0; for ( int i = 0; i < sizeof(dab.byte_buff); ++i ) { cout << hex byte_buff[ i ]; } 

I think this makes it clearer what you are doing and allows the compiler to do all the math.

+2
source

All Articles