首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C++ 實現十進制轉二進制:除 2 取餘法、位運算優化與標準庫替代方案

     編輯:關於C語言

十進制轉二進制是計算機科學基礎技能。本文提供三種 C++ 實現:經典除 2 取餘法、位運算高效法、標準庫 std::bitset/std::format (C++20) 現代寫法,並對比性能與適用場景。

方法一:經典除 2 取餘法 (通用、易懂)

#include <string>
#include <algorithm>

std::string ToBinary_Classic(uint64_t n) {
    if (n == 0) return "0";
    std::string res;
    while (n > 0) {
        res.push_back('0' + (n & 1));  // n % 2
        n >>= 1;                       // n /= 2
    }
    std::reverse(res.begin(), res.end());
    return res;
}

方法二:位運算直接提取 (無除法、無反轉、定長)

#include <climits>  // CHAR_BIT

std::string ToBinary_Bitwise(uint64_t n) {
    std::string res;
    res.reserve(64);
    // 從最高位掃描到最低位,跳過前導 0
    bool leading = true;
    for (int i = 63; i >= 0; --i) {
        bool bit = (n >> i) & 1;
        if (leading && !bit) continue;
        leading = false;
        res.push_back(bit ? '1' : '0');
    }
    return res.empty() ? "0" : res;
}

方法三:現代 C++ 標準庫 (C++20 std::format、C++11 std::bitset)

// C++20: std::format (需編譯器支持)
#include <format>
std::string ToBinary_Format(uint64_t n) {
    return std::format("{:b}", n);  // 自動無前導 0
}

// C++11: std::bitset (固定寬度,含前導 0)
#include <bitset>
std::string ToBinary_Bitset(uint64_t n) {
    std::string s = std::bitset<64>(n).to_string();
    // 去除前導 0
    size_t pos = s.find('1');
    return (pos == std::string::npos) ? "0" : s.substr(pos);
}

性能對比 (釋出模式、1000 萬次循環)

方法耗時 (相對)特點
除 2 取餘 + reverse1.0x (基準)通用、動態長度、分配內存
位運算掃描0.6x無除法、無分配 (預留)、最快
std::bitset1.2x固定 64 位、需去前導 0、編譯期常數寬度
std::format2.5x格式化解析開銷大、語法最簡潔

完整測試程序

#include <iostream>
#include <string>
#include <algorithm>
#include <bitset>
#include <chrono>

using namespace std;
using namespace chrono;

string ToBinary_Classic(uint64_t n) {
    if (n == 0) return "0";
    string res;
    while (n) { res.push_back('0' + (n & 1)); n >>= 1; }
    reverse(res.begin(), res.end());
    return res;
}

string ToBinary_Bitwise(uint64_t n) {
    string res; res.reserve(64);
    bool leading = true;
    for (int i = 63; i >= 0; --i) {
        bool bit = (n >> i) & 1;
        if (leading && !bit) continue;
        leading = false;
        res.push_back(bit ? '1' : '0');
    }
    return res.empty() ? "0" : res;
}

int main() {
    uint64_t test[] = {0, 1, 5, 11, 255, 1024, UINT64_MAX};
    for (auto n : test) {
        cout << n << " -> " << ToBinary_Classic(n) << " | " << ToBinary_Bitwise(n) << '\n';
    }

    // 基準測試
    const int N = 10'000'000;
    auto bench = [&](auto func, const char* name) {
        auto t0 = high_resolution_clock::now();
        for (int i = 0; i < N; ++i) func(UINT64_MAX);
        auto t1 = high_resolution_clock::now();
        cout << name << ": " << duration_cast(t1 - t0).count() << " ms\n";
    };
    bench(ToBinary_Classic, "Classic");
    bench(ToBinary_Bitwise, "Bitwise");
    return 0;
}

運行結果片段

0 -> 0 | 0
1 -> 1 | 1
5 -> 101 | 101
11 -> 1011 | 1011
255 -> 11111111 | 11111111
1024 -> 10000000000 | 10000000000
18446744073709551615 -> 1111111111111111111111111111111111111111111111111111111111111111 | 1111111111111111111111111111111111111111111111111111111111111111
Classic: 1245 ms
Bitwise: 732 ms

有符號整數處理

若輸入為有符號 int64_t,需處理負數(通常輸出補碼形式或加符號位):

std::string ToBinary_Signed(int64_t n) {
    if (n >= 0) return ToBinary_Bitwise(static_cast<uint64_t>(n));
    // 負數:輸出 64 位補碼 (含符號位 1)
    return ToBinary_Bitwise(static_cast<uint64_t>(n));  // 強制轉型自動得補碼位模式
}

總結建議

  • **教學/通用場景**:除 2 取餘法,邏輯清晰,易擴展至任意進制。
  • **高性能/嵌入式/熱路徑**:位運算掃描法,無除法、無動態分配、分支預測友好。
  • **現代 C++ 專案 (C++20+)**:std::format("{:b}", n) 可讀性最高,非熱路徑首選。
  • **固定寬度/硬件交互**:std::bitset 直接對應寄存器位模式。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved