调用std::bitset<N>::test方法时的异常问题及代码对比
用std::bitset实现整数相加时test方法结果异常的问题
我用std::bitset<8>实现了一个两整数相加的函数,但调用返回的result对象的std::bitset<N>::test方法时结果不符合预期——要么始终返回false,要么调试时提示“class "std::bitset<8>" has no member "test"”。
错误实现(结果异常)
这段代码调用r.test时结果错误,但无编译或运行时错误:
std::bitset<8> add(const std::bitset<8>& a, const std::bitset<8>& b) { std::bitset<8> r; for (size_t i = 0; i < a.size(); i++) { r[i] = a.test(i) ^ b.test(i) ^ r.test(i); if (i < a.size() - 1) { r[i + 1] = (a.test(i) && b.test(i)) || (r.test(i) && a.test(i)) || (r.test(i) && b.test(i)); } } return r; }
正确实现(结果正常)
在循环中每次复制result bitset后,调用copy.test则能正常工作:
std::bitset<8> add(const std::bitset<8>& a, const std::bitset<8>& b) { std::bitset<8> r; for (size_t i = 0; i < a.size(); i++) { const auto copy = r; r[i] = a.test(i) ^ b.test(i) ^ copy.test(i); if (i < a.size() - 1) { r[i + 1] = (a.test(i) && b.test(i)) || (copy.test(i) && a.test(i)) || (copy.test(i) && b.test(i)); } } return r; }
运行环境
Windows最新版Visual Studio Community,语言标准设为Preview - Features from the Latest C++ Working Draft (/std:clatest),基于ISO C23标准库模块构建。
完整测试代码
#include <bit> #include <bitset> #include <iostream> std::bitset<8> to_bitset(std::int8_t value) { return { static_cast<std::uint8_t>(value) }; } std::int8_t to_int(const std::bitset<8>& bitset) { return (std::int8_t)bitset.to_ulong(); } std::bitset<8> add_bad_result(const std::bitset<8>& a, const std::bitset<8>& b) { std::bitset<8> r; for (size_t i = 0; i < a.size(); i++) { r[i] = a.test(i) ^ b.test(i) ^ r.test(i); if (i < a.size() - 1) { r[i + 1] = (a.test(i) && b.test(i)) || (r.test(i) && a.test(i)) || (r.test(i) && b.test(i)); } } return r; } std::bitset<8> add_good_result(const std::bitset<8>& a, const std::bitset<8>& b) { std::bitset<8> r; for (size_t i = 0; i < a.size(); i++) { const auto copy = r; r[i] = a.test(i) ^ b.test(i) ^ copy.test(i); if (i < a.size() - 1) { r[i + 1] = (a.test(i) && b.test(i)) || (copy.test(i) && a.test(i)) || (copy.test(i) && b.test(i)); } } return r; } int main() { auto a = 7; auto b = 1; // bad result std::cout << add_bad_result(to_bitset(a), to_bitset(b)) << std::endl; // output: 00001100 // good result std::cout << add_good_result(to_bitset(a), to_bitset(b)) << std::endl; // output: 00001000 return 0; }
问题原因
错误实现的核心问题是计算逻辑依赖了被修改后的当前位值:
在循环的每一轮中,代码先更新了r[i]的结果位,随后计算下一位的进位时,又读取了r[i]——但此时r[i]已经是新的结果位,而非计算进位所需的原始进位输入值,这就导致进位计算逻辑完全错误,最终输出结果不符合预期。
正确实现通过在循环开始时复制当前的r到copy,确保计算当前位和进位时,都基于循环初始状态的r(也就是正确的进位输入),完全符合二进制加法中“用当前位的输入值计算结果位和进位”的逻辑,因此能得到正确结果。
内容的提问来源于stack exchange,提问作者LV-426 Survivor
相关产品推荐
相关产品推荐

