C/ c++等效于Java的doubleToRawLongBits()

时间:2021-06-07 21:00:41

In Java Double.doubleToLongBits() is useful for implementing hashCode() methods.

在Java中,doubletolongbits()对于实现hashCode()方法很有用。

I'm trying to do the same in C++ and write my own doubleToRawLongBits() method, as after trawling through Google I can't find a suitable implementation.

我尝试在c++中执行相同的操作,并编写自己的doubleToRawLongBits()方法,因为在通过谷歌搜索之后,我找不到合适的实现。

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

我可以从std::frexp(numbr,&exp)中得到信号和指数,并且可以确定符号,但不能确定使用位操作符来获得Java等效项。

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

例如,Java的double . doubletolongbits()返回的是double 3.94:

4616054510065937285

4616054510065937285

Thanks for any help.

感谢任何帮助。

Graham

格雷厄姆

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

下面是复制粘贴的文档。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);

3 个解决方案

#1


4  

#include <stdint.h>

static inline uint64_t doubleToRawBits(double x) {
    uint64_t bits;
    memcpy(&bits, &x, sizeof bits);
    return bits;
}

#2


8  

A simple cast 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 the sign bit and exponent bits are depends on your platform and the endianness. If your floats are IEE754, if the sign and exponent are at the front and if CHAR_BIT == 8, you can try this:

符号位和指数位取决于你的平台和发现。如果你的浮点数是IEE754,如果符号和指数在前面,如果CHAR_BIT == 8,你可以试试这个:

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

(In C, say (const unsigned char *)(&d) for the cast.)

(在C中,在cast中(const unsigned char *)(&d)。)

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

更新:要用相同的位创建一个整数,你必须先做整数,然后再复制:

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

For this you have to bear several things in mind: the size of the integer has to be sufficient (a static assertion for sizeof(double) <= sizeof(unsigned long long int) should do the trick), and if the integer is in fact larger, then you're only copying into parts of it. I'm sure you'll figure that out, though :-) (You could use some template magic to create an integer of the correct size, if you really wanted.)

为此,您必须记住以下几件事:整数的大小必须足够(对sizeof(double) <= sizeof(未签名的long long int)进行静态断言),如果这个整数实际上更大,那么您只需要将其复制到其中的一部分。我相信你会明白的:-)(如果你真的想要的话,你可以用一些模板魔术来创建一个正确大小的整数。)

#3


2  

I like unions for these kinds of things.

我喜欢这种东西的结合。

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 it makes it more clear what you're doing and lets the compiler do all the math.

我想这会让你更清楚你在做什么,让编译器做所有的数学运算。

#1


4  

#include <stdint.h>

static inline uint64_t doubleToRawBits(double x) {
    uint64_t bits;
    memcpy(&bits, &x, sizeof bits);
    return bits;
}

#2


8  

A simple cast 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 the sign bit and exponent bits are depends on your platform and the endianness. If your floats are IEE754, if the sign and exponent are at the front and if CHAR_BIT == 8, you can try this:

符号位和指数位取决于你的平台和发现。如果你的浮点数是IEE754,如果符号和指数在前面,如果CHAR_BIT == 8,你可以试试这个:

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

(In C, say (const unsigned char *)(&d) for the cast.)

(在C中,在cast中(const unsigned char *)(&d)。)

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

更新:要用相同的位创建一个整数,你必须先做整数,然后再复制:

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

For this you have to bear several things in mind: the size of the integer has to be sufficient (a static assertion for sizeof(double) <= sizeof(unsigned long long int) should do the trick), and if the integer is in fact larger, then you're only copying into parts of it. I'm sure you'll figure that out, though :-) (You could use some template magic to create an integer of the correct size, if you really wanted.)

为此,您必须记住以下几件事:整数的大小必须足够(对sizeof(double) <= sizeof(未签名的long long int)进行静态断言),如果这个整数实际上更大,那么您只需要将其复制到其中的一部分。我相信你会明白的:-)(如果你真的想要的话,你可以用一些模板魔术来创建一个正确大小的整数。)

#3


2  

I like unions for these kinds of things.

我喜欢这种东西的结合。

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 it makes it more clear what you're doing and lets the compiler do all the math.

我想这会让你更清楚你在做什么,让编译器做所有的数学运算。