提问人:Jesse Emond 提问时间:9/8/2011 最后编辑:CommunityJesse Emond 更新时间:1/17/2023 访问量:473958
如何打印(使用 cout)二进制形式的数字?
How to print (using cout) a number in binary form?
问:
我正在学习一门关于操作系统的大学课程,我们正在学习如何从二进制转换为十六进制,从十进制转换为十六进制等,今天我们刚刚学习了如何使用两者的补码(~数字+1)将有符号/无符号数字存储在内存中。
我们有几个练习要在纸上做,我希望能够在将我的作业提交给老师之前验证我的答案。我为前几个练习编写了一个 C++ 程序,但现在我陷入了如何用以下问题验证我的答案:
char a, b;
short c;
a = -58;
c = -315;
b = a >> 3;
我们需要在内存中显示 和 的二进制表示。a
b
c
我已经在纸上完成了它,它给了我以下结果(所有二进制表示在二的补码之后存储数字):
a = 00111010(它是一个字符,所以 1 个字节)
b = 00001000(它是一个字符,所以 1 个字节)
c = 11111110 11000101(很短,所以 2 个字节)
有没有办法验证我的答案?C++ 中是否有标准方法可以在数字的内存中显示二进制表示,或者我是否必须自己编写每个步骤(计算两者的补码,然后转换为二进制)?我知道后者不会花这么长时间,但我很好奇是否有标准方法可以做到这一点。
答:
这是你要找的吗?
std::cout << std::hex << val << std::endl;
评论
</argument>
C++ 中是否有标准方法可以在数字 [...] 的内存中显示二进制表示?
不。没有 、 like 或 ,但自己输出一个数字二进制并不难:std::bin
std::hex
std::dec
您可以通过屏蔽所有其他位来输出最左边的位,左移,然后对您拥有的所有位重复此操作。
(类型中的位数为 。sizeof(T) * CHAR_BIT
最简单的方法可能是创建一个表示值的 std::bitset
,然后将其流式传输到 .cout
#include <bitset>
...
char a = -58;
std::bitset<8> x(a);
std::cout << x << '\n';
short c = -315;
std::bitset<16> y(c);
std::cout << y << '\n';
评论
bitset
-58 >> 3
bitset
to_string
如果要显示任何对象的位表示形式,而不仅仅是整数,请记住先重新解释为 char 数组,然后您可以将该数组的内容打印为十六进制,甚至二进制(通过位集):
#include <iostream>
#include <bitset>
#include <climits>
template<typename T>
void show_binrep(const T& a)
{
const char* beg = reinterpret_cast<const char*>(&a);
const char* end = beg + sizeof(a);
while(beg != end)
std::cout << std::bitset<CHAR_BIT>(*beg++) << ' ';
std::cout << '\n';
}
int main()
{
char a, b;
short c;
a = -58;
c = -315;
b = a >> 3;
show_binrep(a);
show_binrep(b);
show_binrep(c);
float f = 3.14;
show_binrep(f);
}
请注意,大多数常见的系统都是 little-endian,因此输出不是您期望的1111111 011000101,因为这不是它在内存中的存储方式。如果您正在寻找二进制中的值表示,那么一个简单的方法就可以了。show_binrep(c)
cout << bitset<16>(c)
与已经发布的内容类似,只需使用位移和掩码来获取位;可用于任何类型,作为一个模板(只是不确定是否有标准方法可以在 1 个字节中获取位数,我在这里使用了 8 个)。
#include<iostream>
#include <climits>
template<typename T>
void printBin(const T& t){
size_t nBytes=sizeof(T);
char* rawPtr((char*)(&t));
for(size_t byte=0; byte<nBytes; byte++){
for(size_t bit=0; bit<CHAR_BIT; bit++){
std::cout<<(((rawPtr[byte])>>bit)&1);
}
}
std::cout<<std::endl;
};
int main(void){
for(int i=0; i<50; i++){
std::cout<<i<<": ";
printBin(i);
}
}
评论
CHAR_BIT
使用动态转换为 。没有临时变量,没有循环,没有函数,没有宏。std::bitset
#include <iostream>
#include <bitset>
int main() {
int a = -58, b = a>>3, c = -315;
std::cout << "a = " << std::bitset<8>(a) << std::endl;
std::cout << "b = " << std::bitset<8>(b) << std::endl;
std::cout << "c = " << std::bitset<16>(c) << std::endl;
}
指纹:
a = 11000110
b = 11111000
c = 1111111011000101
评论
x
std::cout << std::bitset<8*sizeof(x)>(x)
这是获得数字的二进制表示的真正方法:
unsigned int i = *(unsigned int*) &x;
评论
#include <iostream>
#include <cmath> // in order to use pow() function
using namespace std;
string show_binary(unsigned int u, int num_of_bits);
int main()
{
cout << show_binary(128, 8) << endl; // should print 10000000
cout << show_binary(128, 5) << endl; // should print 00000
cout << show_binary(128, 10) << endl; // should print 0010000000
return 0;
}
string show_binary(unsigned int u, int num_of_bits)
{
string a = "";
int t = pow(2, num_of_bits); // t is the max number that can be represented
for(t; t>0; t = t/2) // t iterates through powers of 2
if(u >= t){ // check if u can be represented by current value of t
u -= t;
a += "1"; // if so, add a 1
}
else {
a += "0"; // if not, add a 0
}
return a ; // returns string
}
评论
int t = pow(2, num_of_bits - 1);
可重用功能:
template<typename T>
static std::string toBinaryString(const T& x)
{
std::stringstream ss;
ss << std::bitset<sizeof(T) * 8>(x);
return ss.str();
}
用法:
int main(){
uint16_t x=8;
std::cout << toBinaryString(x);
}
这适用于所有类型的整数。
使用旧的 C++ 版本,您可以使用以下代码片段:
template<typename T>
string toBinary(const T& t)
{
string s = "";
int n = sizeof(T)*8;
for(int i=n-1; i>=0; i--)
{
s += (t & (1 << i))?"1":"0";
}
return s;
}
int main()
{
char a, b;
short c;
a = -58;
c = -315;
b = a >> 3;
cout << "a = " << a << " => " << toBinary(a) << endl;
cout << "b = " << b << " => " << toBinary(b) << endl;
cout << "c = " << c << " => " << toBinary(c) << endl;
}
a = => 11000110
b = => 11111000
c = -315 => 1111111011000101
评论
使用 std::bitset 答案和便捷模板:
#include <iostream>
#include <bitset>
#include <climits>
template<typename T>
struct BinaryForm {
BinaryForm(const T& v) : _bs(v) {}
const std::bitset<sizeof(T)*CHAR_BIT> _bs;
};
template<typename T>
inline std::ostream& operator<<(std::ostream& os, const BinaryForm<T>& bf) {
return os << bf._bs;
}
像这样使用它:
auto c = 'A';
std::cout << "c: " << c << " binary: " << BinaryForm{c} << std::endl;
unsigned x = 1234;
std::cout << "x: " << x << " binary: " << BinaryForm{x} << std::endl;
int64_t z { -1024 };
std::cout << "z: " << z << " binary: " << BinaryForm{z} << std::endl;
生成输出:
c: A binary: 01000001
x: 1234 binary: 00000000000000000000010011010010
z: -1024 binary: 1111111111111111111111111111111111111111111111111111110000000000
在 C++20 中,您可以使用 std::format
来执行此操作:
unsigned char a = -58;
std::cout << std::format("{:b}", a);
输出:
11000110
在较旧的系统上,您可以使用 {fmt} 库,是基于。{fmt} 还提供了使此操作更加简单和高效的功能 (godbolt):std::format
print
unsigned char a = -58;
fmt::print("{:b}", a);
免责声明:我是 {fmt} 和 C++20 的作者。std::format
评论
std::format
在 Visual Studio 2019 中尚不可用,是吗?
std::format
#include <format>
/std:c++latest
我在网上玩竞技编码游戏时遇到了这个问题。这是一个快速实施且相当直观的解决方案。它还避免输出前导零或依赖<bitset>
std::string s;
do {
s = std::to_string(r & 1) + s;
} while ( r>>=1 );
std::cout << s;
但是,您应该注意,此解决方案将增加您的运行时间,因此,如果您正在竞争优化或根本不竞争,则应使用此页面上的其他解决方案之一。
评论
std::hex