使用 std::bitset 进行双重表示
Using std::bitset for double representation
在我的应用程序中,我试图显示双精度变量的位表示。
它适用于较小的双变量。不适用于 10^30 级别。
代码:
#include <iostream>
#include <bitset>
#include <limits>
#include <string.h>
using namespace std;
void Display(double doubleValue)
{
bitset<sizeof(double) * 8> b(doubleValue);
cout << "Value : " << doubleValue << endl;
cout << "BitSet : " << b.to_string() << endl;
}
int main()
{
Display(1000000000.0);
Display(2000000000.0);
Display(3000000000.0);
Display(1000000000000000000000000000000.0);
Display(2000000000000000000000000000000.0);
Display(3000000000000000000000000000000.0);
return 0;
}
输出:
/home/sujith% ./a.out
Value : 1e+09
BitSet : 0000000000000000000000000000000000111011100110101100101000000000
Value : 2e+09
BitSet : 0000000000000000000000000000000001110111001101011001010000000000
Value : 3e+09
BitSet : 0000000000000000000000000000000010110010110100000101111000000000
Value : 1e+30
BitSet : 0000000000000000000000000000000000000000000000000000000000000000
Value : 2e+30
BitSet : 0000000000000000000000000000000000000000000000000000000000000000
Value : 3e+30
BitSet : 0000000000000000000000000000000000000000000000000000000000000000
我担心的是为什么 bitset 总是给出 64,后面的 3 为零。有趣的是 "cout" 实际值按预期工作。
如果您查看 the std::bitset
constructor,您会发现它采用字符串作为参数,或者采用 整数 。
这意味着您的 double
值将被转换为整数,并且没有标准整数类型可以容纳如此大的值,这会导致 未定义的行为.
如果你想获得 double
的实际位,你需要做一些转换技巧才能使其工作:
unsigned long long bits = *reinterpret_cast<unsigned long long*>(&doubleValue);
注意像这样的type-punning在C++规范中并没有定义,但是只要sizeof(double) == sizeof(unsigned long long)
就可以了。如果您希望行为定义明确,则必须遍历 char
和 char*
.
数组
对于 C++14,std::bitset
现在采用 unsigned long long
构造函数,因此这可能有效:
union udouble {
double d;
unsigned long long u;
};
void Display(double doubleValue)
{
udouble ud;
ud.d = doubleValue;
bitset<sizeof(double) * 8> b(ud.u);
cout << "Value : " << doubleValue << endl;
cout << "BitSet : " << b.to_string() << endl;
}
这应该为您提供双精度数的内部表示。请参阅 IdeOne.
上的工作示例代码
在我的应用程序中,我试图显示双精度变量的位表示。 它适用于较小的双变量。不适用于 10^30 级别。
代码:
#include <iostream>
#include <bitset>
#include <limits>
#include <string.h>
using namespace std;
void Display(double doubleValue)
{
bitset<sizeof(double) * 8> b(doubleValue);
cout << "Value : " << doubleValue << endl;
cout << "BitSet : " << b.to_string() << endl;
}
int main()
{
Display(1000000000.0);
Display(2000000000.0);
Display(3000000000.0);
Display(1000000000000000000000000000000.0);
Display(2000000000000000000000000000000.0);
Display(3000000000000000000000000000000.0);
return 0;
}
输出:
/home/sujith% ./a.out
Value : 1e+09
BitSet : 0000000000000000000000000000000000111011100110101100101000000000
Value : 2e+09
BitSet : 0000000000000000000000000000000001110111001101011001010000000000
Value : 3e+09
BitSet : 0000000000000000000000000000000010110010110100000101111000000000
Value : 1e+30
BitSet : 0000000000000000000000000000000000000000000000000000000000000000
Value : 2e+30
BitSet : 0000000000000000000000000000000000000000000000000000000000000000
Value : 3e+30
BitSet : 0000000000000000000000000000000000000000000000000000000000000000
我担心的是为什么 bitset 总是给出 64,后面的 3 为零。有趣的是 "cout" 实际值按预期工作。
如果您查看 the std::bitset
constructor,您会发现它采用字符串作为参数,或者采用 整数 。
这意味着您的 double
值将被转换为整数,并且没有标准整数类型可以容纳如此大的值,这会导致 未定义的行为.
如果你想获得 double
的实际位,你需要做一些转换技巧才能使其工作:
unsigned long long bits = *reinterpret_cast<unsigned long long*>(&doubleValue);
注意像这样的type-punning在C++规范中并没有定义,但是只要sizeof(double) == sizeof(unsigned long long)
就可以了。如果您希望行为定义明确,则必须遍历 char
和 char*
.
对于 C++14,std::bitset
现在采用 unsigned long long
构造函数,因此这可能有效:
union udouble {
double d;
unsigned long long u;
};
void Display(double doubleValue)
{
udouble ud;
ud.d = doubleValue;
bitset<sizeof(double) * 8> b(ud.u);
cout << "Value : " << doubleValue << endl;
cout << "BitSet : " << b.to_string() << endl;
}
这应该为您提供双精度数的内部表示。请参阅 IdeOne.
上的工作示例代码