代码之家  ›  专栏  ›  技术社区  ›  Rares Dima

以3的签名权限计数

  •  1
  • Rares Dima  · 技术社区  · 6 年前

    当我们使用基数2二进制进行计数时,每个位都有不同的正值(符号位除外),例如:

     0   0   0  0  0  0  0 
    64  32  16  8  4  2  1
    

    现在我需要在范围内计数 -120 - 120 使用3的有符号幂,我的“位”是:

      0     0    0    0    0   0   0   0    0    0
    -81   -27   -9   -3   -1   1   3   9   27   81
    

    除了在程序开始时记住什么组合会导致哪个值之外,我应该如何找到一种使用这些位进行实际计数的方法?

    用更数学的术语来说,给定一个数字 n 我应该如何找到等于 n .

    作为解决此问题的另一种方法,与其在这些编号格式之间进行直接转换,还可以使用 n 已经转换成这种“3的力量”格式,我可以找到 n+1 直接使用此格式(无需转换回十进制,添加1,然后再转换回十进制)。然而,我也不知道如何朝这个方向前进。

    由于主项目是其核心,是一个更奇特的文件转换器,这是我需要支持使用的文件类型之一,因此我只能使用这种表示数字的方法。

    P、 如果这是一个错误的论坛,请告诉我正确的论坛。我自己也不确定这种问题到底应该问到哪里。

    编辑:的表示形式 0 没有设置位,全部 0 我相信,只要设置了一个位,它的值就会加到这个数字上。

    1 回复  |  直到 6 年前
        1
  •  3
  •   MBo    6 年前

    这是 balanced ternary system 在Setun的电脑里用过的。每个“数字”(-1,0,1)都被称为 trit 类似于bit。

    在没有硬件支持的情况下,您可以使用迭代转换此系统中的数字-获得给定值中三(p)的最大幂,用当前符号填充相应的trit,从值中减去p,调整符号并继续。

    请注意,MST=1(最重要的trit)包含在 (3^n-3^(n-1)-...-1) (3^n+3^(n-1)+...+1) . 例如,2-nd trit(9)是5到13之间的值中最古老的一组。括号中的值是几何级数的和,并且有简短的公式。

    因此,我们可以从第0次trit转移到更重要的trit,重新计算限值。正在使用的Delphi代码,已检查 -40..40 限制

     function ToBTS(Value: Integer): TArray<Integer>;
      var
        p, sgn, t: Integer;
    
        procedure AdjustSign();
        begin
          if value < 0 then begin
             sgn := -sgn;
             value := -value;
          end;
        end;
    
      begin
       SetLength(Result, 8);
       for t := 0 to 7 do
         Result[t] := 0;
       sgn := 1;
       p := 1; // power of three
       t := 0; // trit number
    
       AdjustSign();
       while p * 3 - 1 < 2 * value do begin //forward traversal
         p := p * 3;
         t := t + 1; //move to more significant trit
        end;
    
       while value <> 0 do begin  
          Result[t] := sgn;
          value := value - p;
          AdjustSign();
         //backward traversal
          while (value > 0) and (p - 1 >= 2 * value) do begin
            p := p div 3;
            t := t - 1; //move to less significant trit
          end;
        end;
     end;
    

    输出(+1,-1)

    -13 0---
    -12 0--0
    -11 0--+
    -10 0-0-
    -9 0-00
    -8 0-0+
    -7 0-+-
    -6 0-+0
    -5 0-++
    -4 00--
    -3 00-0
    -2 00-+
    -1 000-
    0 0000
    1 000+
    2 00+-
    3 00+0
    4 00++
    5 0+--
    6 0+-0
    7 0+-+
    8 0+0-
    9 0+00
    10 0+0+
    11 0++-
    12 0++0
    13 0+++