C++ 二元比特流与三元比特流之间的转换?

C++ 二元比特流与三元比特流之间的转换?,c++,algorithm,ternary-representation,C++,Algorithm,Ternary Representation,我需要将任意长度的二进制转换成精确的三元表示。理想情况下,给定一个位数组char buffer[n],该算法将能够生成一个trit数组(模拟位),反之亦然。有这样的算法吗 我知道如何将单个int转换为三值: int nth_trit(int num, int n) { for(int i = 0; i < n; i++) num /= 3; return num % 3; } 短流很简单,因为它非常适合int,所以可以使用nth\u trit函数,但长流

我需要将任意长度的二进制转换成精确的三元表示。理想情况下,给定一个位数组
char buffer[n]
,该算法将能够生成一个trit数组(模拟位),反之亦然。有这样的算法吗

我知道如何将单个
int
转换为三值:

int nth_trit(int num, int n)
{
    for(int i = 0; i < n; i++)
        num /= 3;

    return num % 3;
}

短流很简单,因为它非常适合
int
,所以可以使用
nth\u trit
函数,但长流不可以,因此除了使用大整数库,没有一个简单的解决方案出现在我身上。

如果位缓冲区很长,您的算法就不太好,因为每个输出trit都会重复
n
较小值所需的所有分割。因此,将此算法转换为“bignum”算法并不是您想要的

另一种方法:从左到右扫描位,每个新位都会更新以前的值:

val = val * 2 + bit
具有
n
trits
t[i]
的三元数具有

sum(i = 0 .. n-1) t[i] * 3^i
因此,为新扫描位更新的
val
的三元表示形式变为

[ 2 * sum(i = 0 .. n-1) t[i] * 3^i ] + bit
    = bit + sum(i = 0 .. n-1) 2 * t[i] * 3^i 
    = 2 * t[0] + b + sum(i = 1 .. n) 2 * t[i] * 3^i
为了简化代码,让我们在一个无符号字符数组中计算trit。完成后,你可以按自己喜欢的方式重新包装

#include <stdio.h>

// Compute the trit representation of the bits in the given
// byte buffer.  The highest order byte is bytes[0].  The
// lowest order trit in the output is trits[0].  This is 
// not a very efficient algorithm, but it doesn't use any
// division.  If the output buffer is too small, high order
// trits are lost.
void to_trits(unsigned char *bytes, int n_bytes, 
              unsigned char *trits, int n_trits)
{
  int i_trit, i_byte, mask;

  for (i_trit = 0; i_trit < n_trits; i_trit++)
    trits[i_trit] = 0;

  // Scan bits left to right.
  for (i_byte = 0; i_byte < n_bytes; i_byte++) {

    unsigned char byte = bytes[i_byte];

    for (mask = 0x80; mask; mask >>= 1) {
      // Compute the next bit.
      int bit = (byte & mask) != 0;

      // Update the trit representation
      trits[0] = trits[0] * 2 + bit;
      for (i_trit = 1; i_trit < n_trits; i_trit++) {
        trits[i_trit] *= 2;
        if (trits[i_trit - 1] > 2) {
          trits[i_trit - 1] -= 3;
          trits[i_trit]++;
        }
      }
    }
  }
}

// This test uses 64-bit quantities, but the trit 
// converter will work for buffers of any size.
int main(void)
{
  int i;

  // Make a byte buffer for an easy to recognize value.
  #define N_BYTES 7
  unsigned char bytes [N_BYTES] = 
    { 0xab, 0xcd, 0xef, 0xff, 0xfe, 0xdc, 0xba };

  // Make a trit buffer.  A 64 bit quantity may need up to 42 trits.
  #define N_TRITS 42
  unsigned char trits [N_TRITS];

  to_trits(bytes, N_BYTES, trits, N_TRITS);

  unsigned long long val = 0;
  for (i = N_TRITS - 1; i >= 0; i--) {
    printf("%d", trits[i]);
    val = val * 3 + trits[i];
  }
  // Should prinet value in original byte buffer.
  printf("\n%llx\n", val);

  return 0;
}
#包括
//计算给定数据中位的trit表示
//字节缓冲区。最高顺序字节为字节[0]。这个
//输出中的最低阶trit为trits[0]。这是
//不是一个非常有效的算法,但它不使用任何
//分部。如果输出缓冲区太小,则为高阶
//氚测试仪丢失了。
void to_trits(无符号字符*字节,整数n_字节,
无符号字符*trits,整数n_trits)
{
int i_trit,i_字节,掩码;
对于(i_-trit=0;i_-trit>=1){
//计算下一位。
int位=(字节和掩码)!=0;
//更新trit表示
trits[0]=trits[0]*2+位;
对于(i_-trit=1;i_-trit2){
trits[i_trit-1]=3;
trits[i_trit]++;
}
}
}
}
}
//此测试使用64位量,但trit
//转换器适用于任何大小的缓冲区。
内部主(空)
{
int i;
//为易于识别的值创建字节缓冲区。
#定义N_字节7
无符号字符字节[N_字节]=
{0xab,0xcd,0xef,0xff,0xfe,0xdc,0xba};
//制作一个trit缓冲区。64位数量可能需要多达42个trit。
#定义N_TRITS 42
无符号字符trits[N_trits];
to_trits(字节,N_字节,trits,N_trits);
无符号long val=0;
对于(i=N_TRITS-1;i>=0;i--){
printf(“%d”,trits[i]);
val=val*3+trits[i];
}
//应在原始字节缓冲区中输入净值。
printf(“\n%llx\n”,val);
返回0;
}

乘/除2在任何基数中都很简单,因此将任何基数转换为二进制的最简单方法是重复乘/除2,跟踪进位/奇偶校验

#include <algorithm>
#include <cstdint>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>

// in: a vector representing a bitstring, with most-significant bit first.
// out: a vector representing a tritstring, with least-significant trit first.
static std::vector<uint8_t> b2t(const std::vector<bool>& in) {
  std::vector<uint8_t> out;
  out.reserve(in.size());  // larger than necessary; will trim later
  // for each digit (starting from the most significant bit)
  for (bool carry : in) {
    // add it to the tritstring (starting from the least significant trit)
    for (uint8_t& trit : out) {
      // double the tritstring, carrying overflow to higher places
      uint8_t new_trit = 2 * trit + carry;
      carry = new_trit / 3;
      trit = new_trit % 3;
    }
    if (carry) {
      // overflow past the end of the tritstring; add a most-significant trit
      out.push_back(1);
    }
  }
  out.reserve(out.size());
  return out;
}

// in: a vector representing a tritstring, with most-significant trit first.
// out: a vector representing a bitstring, with least-significant bit first.
static std::vector<bool> t2b(std::vector<uint8_t> in) {
  std::vector<bool> out;
  out.reserve(2 * in.size());  // larger than necessary; will trim later
  bool nonzero;
  do {
    nonzero = false;
    bool parity = false;
    for (uint8_t& trit : in) {
      // halve the tritstring, starting from the most significant trit
      uint8_t new_trit = trit + 3 * parity;
      parity = new_trit & 1;
      nonzero |= trit = new_trit / 2;
    }
    // the division ended even/odd; add a most-signiticant bit
    out.push_back(parity);
  } while (nonzero);
  out.reserve(out.size());
  return out;
}

int main() {
  bool odd = false;
  std::string s;
  while (std::cin >> s) {
    if ((odd = !odd)) {
      std::vector<bool> in(s.size());
      std::transform(s.begin(), s.end(), in.begin(),
          [](char c) {return c - '0';});
      std::vector<uint8_t> out(b2t(in));
      std::copy(out.rbegin(), out.rend(),
          std::ostream_iterator<int>(std::cout));
      std::cout << std::endl;
    } else {
      std::vector<uint8_t> in(s.size());
      std::transform(s.begin(), s.end(), in.begin(),
          [](char c) {return c - '0';});
      std::vector<bool> out(t2b(in));
      std::copy(out.rbegin(), out.rend(),
          std::ostream_iterator<int>(std::cout));
      std::cout << std::endl;
    }
  }
  return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
//in:表示位字符串的向量,首先是最高有效位。
//out:表示trit字符串的向量,首先是最低有效trit。
静态标准::向量b2t(常量标准::向量和输入){
std::向量输出;
out.reserve(in.size());//大于必要值;稍后将修剪
//对于每个数字(从最高有效位开始)
for(bool-carry:in){
//将其添加到trit字符串(从最低有效trit开始)
用于(uint8_t&trit:out){
//将字符串加倍,将溢出的内容带到更高的位置
uint8新的trit=2*trit+进位;
进位=新测试/3;
trit=新的_trit%3;
}
如果(携带){
//溢出超过trit字符串的结尾;添加最重要的trit
向外。向后推(1);
}
}
out.reserve(out.size());
返回;
}
//in:表示trit字符串的向量,首先是最重要的trit。
//out:表示位字符串的向量,首先是最低有效位。
静态std::vector t2b(std::vector in){
std::向量输出;
out.reserve(2*in.size());//比需要的大;稍后将修剪
布尔非零;
做{
非零=假;
布尔奇偶性=假;
用于(uint8_t&trit:in){
//从最重要的trit开始,将trit字符串减半
uint8\u t新的trit=trit+3*奇偶校验;
奇偶性=新测试&1;
非零|=trit=新的| trit/2;
}
//除法以偶数/奇数结束;添加一个最重要的位
向外。向后推(对等);
}while(非零);
out.reserve(out.size());
返回;
}
int main(){
布尔奇数=假;
std::字符串s;
而(标准::cin>>s){
如果((奇数=!奇数)){
std::向量(s.size());
std::transform(s.begin()、s.end()、in.begin(),
[](字符c){返回c-'0';});
标准::矢量输出(b2t(in));
std::copy(out.rbegin(),out.rend(),
std::ostream_迭代器(std::cout));

std::cout可以显示每个三进制数字都依赖于所有的二进制数字。因此,你最好读取整个位串,然后进行转换。

平衡三进制/三进制更好。{-1,0,1}以这种方式进行输出。

一个trit实际上代表大约1.58496~log(3)信息位。如果我理解正确,你是说我可以取,即每3位,将它们转换为2个Trit,因为Trit大约代表1.5位。不幸的是,3位(2^3)并不完全由2个Trit(3^2)表示。我需要一个精确的表示。你的“位”数组是什么一个由
'0'
'1'
字符值组成的数组?还是一个将逐位“分解”的8位数字数组(即通过
第n个trit
函数)?如图所示
#include <algorithm>
#include <cstdint>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>

// in: a vector representing a bitstring, with most-significant bit first.
// out: a vector representing a tritstring, with least-significant trit first.
static std::vector<uint8_t> b2t(const std::vector<bool>& in) {
  std::vector<uint8_t> out;
  out.reserve(in.size());  // larger than necessary; will trim later
  // for each digit (starting from the most significant bit)
  for (bool carry : in) {
    // add it to the tritstring (starting from the least significant trit)
    for (uint8_t& trit : out) {
      // double the tritstring, carrying overflow to higher places
      uint8_t new_trit = 2 * trit + carry;
      carry = new_trit / 3;
      trit = new_trit % 3;
    }
    if (carry) {
      // overflow past the end of the tritstring; add a most-significant trit
      out.push_back(1);
    }
  }
  out.reserve(out.size());
  return out;
}

// in: a vector representing a tritstring, with most-significant trit first.
// out: a vector representing a bitstring, with least-significant bit first.
static std::vector<bool> t2b(std::vector<uint8_t> in) {
  std::vector<bool> out;
  out.reserve(2 * in.size());  // larger than necessary; will trim later
  bool nonzero;
  do {
    nonzero = false;
    bool parity = false;
    for (uint8_t& trit : in) {
      // halve the tritstring, starting from the most significant trit
      uint8_t new_trit = trit + 3 * parity;
      parity = new_trit & 1;
      nonzero |= trit = new_trit / 2;
    }
    // the division ended even/odd; add a most-signiticant bit
    out.push_back(parity);
  } while (nonzero);
  out.reserve(out.size());
  return out;
}

int main() {
  bool odd = false;
  std::string s;
  while (std::cin >> s) {
    if ((odd = !odd)) {
      std::vector<bool> in(s.size());
      std::transform(s.begin(), s.end(), in.begin(),
          [](char c) {return c - '0';});
      std::vector<uint8_t> out(b2t(in));
      std::copy(out.rbegin(), out.rend(),
          std::ostream_iterator<int>(std::cout));
      std::cout << std::endl;
    } else {
      std::vector<uint8_t> in(s.size());
      std::transform(s.begin(), s.end(), in.begin(),
          [](char c) {return c - '0';});
      std::vector<bool> out(t2b(in));
      std::copy(out.rbegin(), out.rend(),
          std::ostream_iterator<int>(std::cout));
      std::cout << std::endl;
    }
  }
  return 0;
}
$ ./a.out 1011 102 102 1011 10001100001101010011010010111000011011101000111101011101000110100101101101111110110011010010111100010110100010101011010100101100001101001000000111011110101001000100011010111011000111101110111001111110110011101011101101001001110010111111100011000110011000111110110111011110110110001111011011011000100101010010111010000110101011010100011010110110000010110111000111000110101000000110000001111110101110010000011000110001010000001001100011000000100100100001100101111000101001001010101101101000011100110001111011110001 12010110110220200020211012001000211110222212120220002002120120111221021120100122221020011120010202110111112112110201211201120222000011010100122122121211112101111121002110102112000111200002121211002022100220211220220111010210200222021221020122012102101010100001122200011110210221120122022011202201002002001221211001221112001 12010110110220200020211012001000211110222212120220002002120120111221021120100122221020011120010202110111112112110201211201120222000011010100122122121211112101111121002110102112000111200002121211002022100220211220220111010210200222021221020122012102101010100001122200011110210221120122022011202201002002001221211001221112001 10001100001101010011010010111000011011101000111101011101000110100101101101111110110011010010111100010110100010101011010100101100001101001000000111011110101001000100011010111011000111101110111001111110110011101011101101001001110010111111100011000110011000111110110111011110110110001111011011011000100101010010111010000110101011010100011010110110000010110111000111000110101000000110000001111110101110010000011000110001010000001001100011000000100100100001100101111000101001001010101101101000011100110001111011110001 ^D