Tôi gặp sự cố liên quan đến số lượng lớn các số nguyên nhỏ (thực tế là chữ số thập phân). Không gian hiệu quả cách để lưu trữ dữ liệu như vậy là gì?Lưu trữ một số thập phân
Bạn nên sử dụng std::bitset<4>
để lưu trữ một chữ số thập phân?
Tôi gặp sự cố liên quan đến số lượng lớn các số nguyên nhỏ (thực tế là chữ số thập phân). Không gian hiệu quả cách để lưu trữ dữ liệu như vậy là gì?Lưu trữ một số thập phân
Bạn nên sử dụng std::bitset<4>
để lưu trữ một chữ số thập phân?
Bạn nên sử dụng std :: bitset < 4> để lưu trữ một chữ số thập phân?
Vâng, về nguyên tắc đó là một ý tưởng hay. Đó là một tối ưu hóa nổi tiếng và được gọi là mã hóa BCD.
(chữ số thập phân thực sự). Không gian hiệu quả cách để lưu trữ dữ liệu như vậy là gì?
Bạn có thể thu nhỏ biểu thị chữ số thập phân bằng cách sử dụng một nibble của byte bị chiếm đóng. Toán học cũng có thể được áp dụng tối ưu hóa, so với biểu diễn các chữ số ASCII hoặc như vậy.
std::bitset<4>
sẽ không phân phát tốt cho việc nén dữ liệu.
std::bitset<4>
sẽ vẫn chiếm một byte đầy đủ.
Một cấu trúc dữ liệu thay thế tôi có thể nghĩ đến là một bitfield
// Maybe #pragma pack(push(1))
struct TwoBCDDecimalDigits {
uint8_t digit1 : 4;
uint8_t digit2 : 4;
};
// Maybe #pragma pack(pop)
Thậm chí còn có một thư viện có sẵn, để chuyển đổi định dạng này sang định dạng số bình thường hỗ trợ tại mục tiêu CPU kiến trúc của bạn:
Một cách khác tôi có thể nghĩ đến là viết lớp của riêng bạn:
class BCDEncodedNumber {
enum class Sign_t : char {
plus = '+' ,
minus = '-'
};
std::vector<uint8_t> doubleDigitsArray;
public:
BCDEncodedNumber() = default;
BCDEncodedNumber(int num) {
AddDigits(num); // Implements math operation + against the
// current BCD representation stored in
// doubleDigitsArray.
}
};
Tất cả các đối tượng trong C++ sẽ nhất thiết phải mất tối thiểu 1 byte, vì vậy nếu bạn sử dụng 'bitset <4>', bạn không đạt được bất kỳ thứ gì chỉ bằng cách sử dụng 'char'. –
@MatteoItalia OK, đó là một sự hiểu lầm. Tôi đã không có nghĩa là sử dụng một byte đầy đủ cho mỗi chữ số 0-9 nhưng sử dụng các nibbles của một byte đơn. Hãy để tôi sửa chữa câu trả lời của tôi. – user0042
Chắc chắn tốt hơn, mặc dù IMHO sử dụng bitfield ở đây chỉ là một trở ngại - nói rằng bạn có một vectơ 'TwoBCDDecimalDigits', bây giờ để truy cập vào chữ số thứ n, bạn phải lấy phần tử n/2 và sau đó có nếu n % 2 để quyết định thành viên nào cần đọc. Nếu nó chỉ là một mảng 'uint8_t', như trong giải pháp thứ hai của bạn, bạn chỉ có thể dịch chuyển mà không có nhánh (n-th digit =' mảng [n >> 1] >> ((n & 1) << 2) '). –
Tùy thuộc vào cách không gian hiệu quả nó phải được và hiệu quả như thế nào hồi nên, tôi thấy hai khả năng:
Vì vector của std::bitset<4>
là (theo như tôi biết) được lưu trữ trong cài đặt chưa được giải nén (mỗi bitet được lưu trữ trong một từ bộ nhớ, 32 hoặc 64 bit), bạn nên sử dụng một biểu diễn đóng gói như Từ 64 bit để lưu trữ 16 chữ số:
store (if the digit was not stored before):
block |= digit << 4 * index
load:
digit = (block >> 4 * index) & 0xF
reset:
block &= ~(0xF << 4 * index);
Một vectơ của các từ 64 bit này (uint64_t) cùng với một số phương pháp truy cập phải dễ triển khai.
Nếu bạn muốn một cách rất nhỏ gọn, thì không, sử dụng bitset<4>
là một ý tưởng tồi, vì bitset<4>
sẽ sử dụng ít nhất một byte, thay vì 4 bit.
tôi khuyên bạn nên sử dụng std::vector<std::uint32_t>
Bạn có thể lưu trữ nhiều chữ số trong một uint32_t. Hai cách thông thường:
Nếu bạn sử dụng uint64_t
thay vì uint32_t
, sau đó bạn có thể lưu trữ 16 chữ số với cách đầu tiên (cùng 4bit/hiệu quả chữ số), và 19 chữ số với cách thứ hai: efficieny 3.36bit/chữ số, mà là khá chặt chẽ đến mức tối thiểu lý thuyết: ~ 3.3219bit/digit
Điều gì mang lại sizeof cho bitet của bạn? –
Tất cả các chữ số của bạn có phải là số không? Bạn có bao nhiêu số? Bạn có cần truy cập các chữ số theo vị trí của chúng không? Bạn có sẵn sàng giao dịch hiệu suất cho hiệu quả không gian? ** Rõ ràng, trước khi thực hiện loại tối ưu hóa đó, bạn phải tìm ra những gì bạn cần! ** Trong hầu hết các trường hợp, việc sử dụng kiểu số nguyên hoặc char thích hợp có thể là quá đủ. – Phil1970
Ngoài ra, có các mẫu mà bạn có thể khai thác trong chuỗi các chữ số hoặc các phần của chuỗi đó không? Một số chữ số có khả năng xảy ra thường xuyên hơn các chữ số khác không? Nếu có, bạn có thể sử dụng một số mã hóa, thay vì biểu diễn trực tiếp. – Peter