You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 02:44:51