2012-06-08 73 views
9

Tôi phải chuyển đổi số nhị phân như ví dụ unsigned int bin_number = 10101010 vào biểu diễn thập phân của nó (tức là 170) càng nhanh càng tốt? Thuật toán tốt nhất là gì?Cách nhanh chóng để chuyển đổi số nhị phân sang số thập phân

+1

Có '10101010' đến từ người dùng chương trình của bạn hay chỉ là một chữ trong mã? –

+0

Bạn có thể cho hình ảnh rõ hơn về nơi số nhị phân bắt nguồn từ đâu không? Được biết tại thời gian biên dịch hay chỉ có thời gian chạy? Nó được lưu trữ trong một chuỗi hoặc một số cấu trúc khác? Biết được điều này sẽ giúp trả lời câu hỏi dễ dàng hơn nhiều. –

+0

Vâng, tôi xin lỗi. Thông thường tôi nhận được số thời gian chạy, nhưng đôi khi tại thời gian biên dịch. Tôi vẫn đang học. – Nick

Trả lời

10

Sử dụng mẫu bạn có thể giải quyết vấn đề này tại thời gian biên dịch.

template<unsigned long num> 
struct binary 
{ 
    static unsigned const value = 
     binary<num/10>::value << 1 | num % 10; 
}; 

// Specialization for zero 
template<> 
struct binary<0> 
{ static unsigned const value = 0; }; 

Mẫu nhị phân là instantiated một lần nữa với một num nhỏ hơn, cho đến khi đạt num zero và chuyên môn hóa được sử dụng như một điều kiện chấm dứt.

Ví dụ: std::cout << binary<10101010>::value;

Đối thời gian chạy vấn đề:

unsigned binary_to_decimal(unsigned num) 
{ 
    unsigned res = 0; 

    for(int i = 0; num > 0; ++i) 
    { 
     if((num % 10) == 1) 
      res += (1 << i); 

     num /= 10; 
    } 

    return res; 
} 
+0

Bạn có thể làm cho tôi một ví dụ? – Nick

+4

Sử dụng các mẫu mà bạn có thể tính toán bất kỳ thứ gì vào thời gian biên dịch, vì chúng hoàn tất. Tuy nhiên, điều đó có giúp OP không làm được gì không? – PlasmaHH

+1

-1: Tôi nghi ngờ điều đó. Nếu OP có một ICE, cái mà anh ta cần để sử dụng lập trình meta, anh ta chỉ có thể làm 'const double d = 170.0; 'Vì anh ta là sureley nhận được số vào trong thời gian chạy, vì vậy lập trình meta là ra ngoài. –

3

Trên thực tế nếu bạn viết unsigned int bin_number = 10101010, điều này được hiểu là một số thập phân bởi trình biên dịch.

Nếu bạn muốn viết một litteral nhị phân trong mã nguồn của bạn, bạn nên sử dụng BOOST_BINARY.Then bạn chỉ cần in nó bằng cách sử cout, số thập phân là mặc định ...

unsigned int i = BOOST_BINARY(10101010); 
std::cout << i; // This prints 170 
+0

BOOST_BINARY của bạn là gì? – Nick

+0

Một số trình biên dịch cũng hỗ trợ tiền tố "0b" ('i = 0b10101010'), nhưng với việc tăng bạn đảm bảo tính di động. – Aurel

+0

Boost là thư viện C++, hãy xem http://www.boost.org/. – Aurel

7

Vâng, nếu điều này "number" thực sự là một chuỗi nhận được từ một số nguồn (đọc từ một tệp hoặc từ người dùng) mà bạn đã chuyển đổi thành một số (nghĩ rằng nó phù hợp hơn với số thực), rất có thể, bạn có thể sử dụng std::bitset để thực hiện chuyển đổi:

#include <bitset> 

unsigned int number = std::bitset<32>("10101010").to_ulong(); 

(Tất nhiên 32 đây được thực hiện xác định và có thể được viết một cách thích hợp hơn như std::numeric_limits<unsigned int>::digits.)

Nhưng nếu nó thực sự là một con số (số nguyên biến) trong (rất) nơi đầu tiên bạn có thể làm:

#include <string> 

unsigned int number = std::bitset<32>(std::to_string(bin_number)).to_ulong(); 

(sử dụng C++ 11 to_string) Nhưng điều này có lẽ sẽ không phải là cách hiệu quả nhất nữa, vì những người khác đã trình bày thuật toán hiệu quả hơn dựa trên các con số. Nhưng như đã nói, tôi nghi ngờ rằng bạn thực sự nhận được con số này như là một biến số nguyên thực tế ở nơi đầu tiên, nhưng thay vì đọc nó từ một số tập tin văn bản hoặc từ người sử dụng.

+0

Cảm ơn, đây là câu trả lời hay, nhưng con số không phải là một chuỗi, tôi không thể sử dụng C++ 11 và tôi đã yêu cầu giải pháp nhanh! – Nick

+0

@Nick Vì vậy, tôi có thể hỏi bạn lấy nó từ đâu, bạn rõ ràng phải lấy nó từ đâu đó và tôi nghi ngờ bạn thực sự đọc một số nhị phân, đại diện cho một số chỉ chứa số 0 và 1, đó sẽ là rác.Nó thực sự chỉ có ý nghĩa để có được một số như vậy từ một số phương tiện văn bản ở nơi đầu tiên. Ngoại lệ duy nhất là khi bạn cần hằng số nhị phân, nhưng đối với điều này bạn chỉ có thể sử dụng một phương pháp khác (chương trình mẫu của gliderkite là rất tốt đẹp). Nhưng đối với hầu hết các trường hợp khi nó đến như là một chuỗi, các giải pháp bitet không phải là một trong những chậm nhất (và nó không cần C + + 11, hoặc là). –

+0

btw bạn nhận được +1 của tôi – Nick

0

Nếu bạn biết số lượng chữ số nhị phân mà bạn đang làm việc với nó luôn luôn cố định số nhị phân đi kèm trong một chuỗi (vì nó sẽ nếu đọc từ một tập tin hoặc stdin) trong thời gian chạy (tức là không thể chuyển đổi thời gian biên dịch), bạn có thể áp dụng phương pháp này:

int to_binary(const char* c) 
{ 
    return ((c[0] & 1) ? 0x80 : 0x00) | 
      ((c[1] & 1) ? 0x40 : 0x00) | 
      ((c[2] & 1) ? 0x20 : 0x00) | 
      ((c[3] & 1) ? 0x10 : 0x00) | 
      ((c[4] & 1) ? 0x08 : 0x00) | 
      ((c[5] & 1) ? 0x04 : 0x00) | 
      ((c[6] & 1) ? 0x02 : 0x00) | 
      ((c[7] & 1) ? 0x01 : 0x00); 
} 

Giả định số nhị phân 8 chữ số cố định.gọi là như thế này:

std::cout << to_binary("10101010") << std::endl; 

Nếu bạn đã có một số chút mười sáu bạn vẫn có thể sử dụng nó:

const char* bin_number = "1010101010101010"; 

// Deal with 16 bits 
std::cout << (to_binary(bin_number) << 8 | to_binary(bin_number + 8)) << std::endl; 

Lưu ý rằng có rõ ràng là không có giới hạn kiểm tra ở đây và tôi đang dựa vào thực tế là LSB của '1' luôn là 1 và '0' luôn là 0 (vì vậy không xác thực rằng đó thực sự là đầu vào nhị phân.)

Đương nhiên, nó khá cụ thể và không linh hoạt, nhưng nó thực hiện công việc và tôi không chắc rằng bạn sẽ nhanh hơn nhiều.

Các vấn đề liên quan