std::bitset适用于编译期确定位宽的整数转二进制字符串,但会静默截断、不支持运行时位宽;大数需用std::from_chars或手写字符串除法;二进制转十进制须字符串模拟乘加。

用 std::bitset 将整数转二进制字符串(限固定位宽)
如果整数范围确定(比如总在 int 32 位内),std::bitset 是最简洁的选择,但要注意它要求编译期知道位宽。
常见错误是直接传变量给模板参数:std::bitset<n></n> 中的 n 必须是常量表达式,不能是运行时变量。
- 对
unsigned int转 32 位二进制:std::bitset(x).to_string() - 要去掉前导零?得手动截取:
auto s = std::bitset(x).to_string(); s.erase(0, s.find_first_not_of('0'));(注意全零时find_first_not_of返回std::string::npos,需判断) - 位宽太小会静默截断——比如
std::bitset(257)得到的是"00000001",高位丢失不报错
用 std::to_chars 或 std::stringstream 实现任意长度十进制字符串转整数
这是反向转换的关键一步:先解析字符串为整型,再转二进制。别直接手写除二法——容易溢出且不处理非法字符。
std::stoi 看似简单,但遇到超长数字(如 "12345678901234567890")会抛 std::out_of_range;而 std::stoll 也只撑到 64 位。
立即学习“C++免费学习笔记(深入)”;
- 安全做法:用
std::from_chars(C++17),它不抛异常、可精确控制解析范围、返回解析结束位置:long long val; auto [ptr, ec] = std::from_chars(s.data(), s.data() + s.size(), val);
- 若字符串可能超
long long范围,就得上大数库(如boost::multiprecision)或自己实现字符串除法 -
std::stringstream可读但性能差、错误处理弱,仅适合原型验证
手写循环除二法转二进制字符串(无位宽限制,需处理负数)
当输入十进制字符串可能极大,或你想完全掌控逻辑时,必须自己实现。核心是模拟小学除法,但操作对象是字符串而非整数。
关键难点不在算法本身,而在边界:空字符串、全零、负号、单个 '0' 的处理。
- 先检查首字符是否为
'-',记录符号后跳过;结果字符串最后加'-' - 每次用整个字符串对 2 取模得当前二进制位(余数只能是 0 或 1),再做整除(字符串减余数后逐位除以 2)
- 避免反复
push_front(低效):把每位余数push_back到 vector,最后std::reverse - 输入
"0"必须特判,否则循环进不去,结果为空
二进制字符串转十进制字符串(从高位开始累加乘法)
这是最容出错的方向:不能用 std::stoi 解析二进制字符串——它只认十进制格式。必须按位计算 result = result * 2 + (c == '1'),但 result 类型不能是内置整型(会溢出)。
所以本质是字符串版的大数乘加:维护一个十进制字符串 res,遍历二进制串每个字符:
- 对当前
res执行“乘 2”:从末位开始逐位*2 + 进位,生成新字符串 - 加上当前位(0 或 1):字符串加法,注意进位传播
- 起始
res = "0";若输入含前导零(如"00101"),不影响结果,无需预处理 - 整个过程没有浮点、没有溢出风险,但要注意空输入和非法字符(非
'0'/'1')校验
真正麻烦的从来不是“怎么写”,而是“谁来保证输入合法”和“位数爆炸后性能怎么扛”。生产环境建议优先用 boost::multiprecision::cpp_int,它内置了 to_binary_string 和 from_binary_string,且自动处理符号、前导零、异常。


















