Balanced ternary arithmetics

Balanced Ternary Numeral System - forum was moved from http://ternary.info

Moderator: haqreu

Mac Buster
Retired
Posts: 1474
Joined: 03 Aug 2003 22:37
Location: Moscow

Balanced ternary arithmetics

Post by Mac Buster »

Due to rising interests to implementation of arithmetics operations in balanced ternary system I decided to publish some source code, that was written by Mr. James Allwright, since his web-site - http://perun.hscs.wmin.ac.uk/~jra/ternary/ - is no longer available. The code is in C language and shows how to perform some elementary operations.

Code: Select all

/* Package of routines for arithmetic in balanced ternary */
/* Numbers are held as an array of size lena stored least */
/* significant byte first */

/* Developed by James Allwright,                   */
/* Department of Electronics and Computer Science, */
/* University of Southampton, UK                   */

#define MAXLEN 50

static int plus_one[MAXLEN] = {1};
static int len_plus_one = 1;

add(lena, lenb, lenc, a, b, c)
/* c = a + b */
/* add together 2 numbers in balanced ternary */
int *lena, *lenb, *lenc;
int a[MAXLEN], b[MAXLEN], c[MAXLEN];
{
  int carry, i;

  zero(lenc, c);
  carry = 0;
  i = 0;
  while ((carry != 0) || (i < *lena) || (i < *lenb)) {
    c[i] = carry;
    if (i < *lena) {
      c[i] = c[i] + a[i];
    };
    if (i < *lenb) {
      c[i] = c[i] + b[i];
    };
    carry = 0;
    if (c[i] > 1) {
      c[i] = c[i] - 3;
      carry = 1;
    };
    if (c[i] < -1) {
      c[i] = c[i] + 3;
      carry = -1;
    };
    i = i + 1;
    if ((i >= MAXLEN) && (carry != 0)) {
      printf("Overflow error!\n");
      exit(-1);
    };
  };
  *lenc = i+1;
  while ((*lenc > 0) && (c[*lenc-1] == 0)) {
    *lenc = *lenc -1;
  };
};

negate(lena, a)
/* a = -a */
int *lena;
int a[MAXLEN];
{
  int i;

  for (i=0; i < *lena; i++) {
    a[i] = -a[i];
  };
};

neg(lena, lenb, a, b)
/* b = -a */
int *lena, *lenb;
int a[MAXLEN], b[MAXLEN];
{
  int i;

  for (i=0; i < *lena; i++) {
    b[i] = -a[i];
  };
  *lenb = *lena;
};

sub(lena, lenb, lenc, a, b, c)
/* c = a - b */
/* subtract numbers in balanced ternary */
/* using negate and add */
int *lena, *lenb, *lenc;
int a[MAXLEN], b[MAXLEN], c[MAXLEN];
{
  int lent;
  int temp[MAXLEN];
  /* temp = -b */
  neg(lenb, &lent, b, temp);
  add(lena, &lent, lenc, a, temp, c);
};

copy(lena, lenb, a, b)
/* copies a into b */
int *lena, *lenb;
int a[MAXLEN], b[MAXLEN];
{
  int i;

  for (i=0; i<*lena; i++) {
    b[i] = a[i];
  };
  *lenb = *lena;
};

zero(lena, a)
/* a = 0 */
/* sets a to zero */
int *lena;
int a[MAXLEN];
{
  int i;

  for (i=0; i<MAXLEN; i++) {
    a[i] = 0;
  };
  *lena = 0;
};

mshift(lena, a)
/* shift left one place (multiply by 3) */
int *lena;
int a[MAXLEN];
{
  int i;

  if (*lena >= MAXLEN ) {
    printf("Overflow error in mshift\n");
    exit(-1);
  };
  *lena = *lena + 1;
  for (i=*lena-1; i>0; i--) {
    a[i] = a[i-1];
  };
  a[0] = 0;
};

dshift(lena, a)
/* shift right one place (divide by 3) */
int *lena;
int a[MAXLEN];
{
  int i;

  if (*lena > 0) {
    *lena = *lena - 1;
    for (i=0; i<*lena; i++) {
      a[i] = a[i+1];
    };
  };
};

mul(lena, lenb, lenc, a, b, c)
/* multiply together 2 numbers in balanced ternary */
int *lena, *lenb, *lenc;
int a[MAXLEN], b[MAXLEN], c[MAXLEN];
{
  int lend, lent;
  int d[MAXLEN], temp[MAXLEN];
  int i;

  zero(lenc, c);
  if (*lena + *lenb - 2 > MAXLEN) {
    printf("Result too large error in multiplication!\n");
    exit(1);
  };
  copy(lenb, &lend, b, d);
  for (i=0; i < *lena; i++) {
    if (a[i] == 1) {
      /* c = c + d */
      add(lenc, &lend, &lent, c, d, temp);
      copy(&lent, lenc, temp, c);
    };
    if (a[i] == -1) {
      /* c = c - d */
      sub(lenc, &lend, &lent, c, d, temp);
      copy(&lent, lenc, temp, c);
    };
    if (i < *lena-1) {
      mshift(&lend, d);
    };
  };
};

int compare(lena, lenb, a, b)
/*  used by div           */
/*  returns :             */
/*    1  if  |a| >  |b|   */
/*    0  if  |a| == |b|   */
/*   -1  if  |a| <  |b|   */

int *lena, *lenb;
int a[MAXLEN], b[MAXLEN];
{
  int signa, signb;
  int place;
  
  if (*lena > *lenb) {
    return(1);
  };
  if (*lena < *lenb) {
    return(-1);
  };
  /* get sign of a and b */
  signa = a[*lena-1];
  signb = b[*lenb-1];
  place = *lena - 1;
  while ((place >= 0) && (signa*a[place] == signb*b[place])) {
    place = place -1;
  };
  if (place == -1) {
    return(0);
  } else {
    if (signa*a[place] > signb*b[place]) {
      return(1);
    } else {
      return(-1);
    };
  };
};

div(lena_in, lenb_in, lenc, lena, a_in, b_in, c, a)
/*  divide numbers in balanced ternary  */
/*  calculates a_in / b_in, returning   */
/*  c = result, a = remainder           */
/*  algorithm is like decimaltoBT       */
/*  a and b are working copies of a_in and b_in */
int *lena_in, *lenb_in, *lenc, *lena;
int a_in[MAXLEN], b_in[MAXLEN], c[MAXLEN], a[MAXLEN];
{
  int lenb_store;
  int *lenb;
  int lent;
  int b[MAXLEN], temp[MAXLEN];
  int pos, digit;

  if (*lenb_in == 0) {
    printf("Division by zero error!\n");
    exit(1);
  };
  if (*lena_in == 0) {
    *lenc = 0;
    return;
  };
  copy(lena_in, lena, a_in, a); /* remainder starts as a */
  lenb = &lenb_store;
  copy(lenb_in, lenb, b_in, b); /* copy in b */
  pos = 0;
  digit = - 1;

  /* align b appropriately */
  while (*lenb < (*lena+1)) {
    mshift(lenb, b);
    pos = pos + 1;
  };
  while (*lenb > (*lena+1)) {
    dshift(lenb, b);
    pos = pos - 1;
  };
  if (pos >= 0) {
    *lenc = pos + 1; /* initial guess at length of result */
  } else {
    *lenc = 0;
  }

  while ((*lena > 0) && (pos >= 0)) {
    /* decide whether to try +b or -b */
    if (a[*lena - 1] == b[*lenb - 1]) {
      digit = - digit;
      /* b = -b */
      neg(lenb, &lent, b, temp);
      copy(&lent, lenb, temp, b);
    };
    /* temp = a + b */
    add(lena, lenb, &lent, a, b, temp);
    if (compare(lena, &lent, a, temp) == 1) {
      /* accept digit */
      /* a = temp */
      copy(&lent, lena, temp, a);
      c[pos] = digit;
    } else {
      /* don't accept digit */
      c[pos] = 0;
    };
    pos = pos - 1;
    dshift(lenb, b);
  };

  /* if we've reduced a to zero, fill in the remaining digits with 0 */
  while (pos >= 0) {
    c[pos] = 0;
    pos = pos - 1;
  };

  /* correct the length of the result */
  while ((*lenc > 0) && (c[*lenc-1] == 0)) {
    *lenc = *lenc - 1;
  };

  /* ensure that the remainder is the same sign as a_in */
  if (*lena > 0) { /* no problem if there is no remainder */
    if (a_in[*lena_in - 1] != a[*lena-1]) {
      if ((a_in[*lena_in - 1] == b_in[*lenb_in-1]) ) {
        /* a = a + b_in */
        add(lena, lenb_in, &lent, a, b_in, temp);
        copy(&lent, lena, temp, a);
        /* c = c - 1 */
        sub(lenc, &len_plus_one, &lent, c, plus_one, temp);
        copy(&lent, lenc, temp, c);
      } else {
        /* a = a - b_in */
        sub(lena, lenb_in, &lent, a, b_in, temp);
        copy(&lent, lena, temp, a);
        /* c = c + 1 */
        add(lenc, &len_plus_one, &lent, c, plus_one, temp);
        copy(&lent, lenc, temp, c);
      };
    };
  };
};

BTtodecimal(lena, a, result)
/* convert Balanced Ternary to decimal */
int *lena;
int a[MAXLEN];
int *result;
{
  int b, i;

  b = 1;
  *result = 0;
  for (i=0; i < (*lena); i++) {
    *result = *result + b * a[i];
    b = b * 3;
  };
};

int abs(a)
int a;
{
  if (a > 0) {
    return(a);
  } else {
    return(-a);
  };
};

decimaltoBT(lenr, result, value)
/* convert decimal to Balanced Ternary */
int *lenr;
int result[MAXLEN];
int value;
{
  int target, val, goal, pos;

  *lenr = 0;
  target = value;
  pos = 0;
  val = 1;
  goal  = 2 * target;
  if (goal < 0) {
    goal = -goal;
  };
  while ((val < goal) && (pos < MAXLEN)) {
    val = 3 * val;
    pos = pos + 1;
  };
  if (pos >= MAXLEN) {
    printf("Overflow error in decimaltoBT\n");
    exit(-1);
  };
  if ( target < 0) {
    val = -val;
  };
  while (pos >= 0) {
    if (abs(target-val) < abs(target)) {
      if (val > 0) {
        result[pos] = 1;
        target = target - val;
      } else {
        result[pos] = -1;
        target = target - val;
      };
      if (*lenr == 0) {
        *lenr = pos+1;
      };
    } else {
      result[pos] = 0;
    };
    val = val / 3;
    pos = pos - 1;
    /* make target and val the same sign */
    if ((target * val) < 0) {
      val = -val;
    };
  };
};

printnum(lena, a)
int *lena;
int a[MAXLEN];
{
  int i;

  for (i=*lena-1; i>=0; i--) {
    printf("(%d)", a[i]);
  };
  if (*lena == 0) printf("(0)");
};

main(argc, argv)
int argc;
char *argv[];
{
  int a[MAXLEN], b[MAXLEN], c[MAXLEN], rem[MAXLEN];
  int lena, lenb, lenc, lenrem;
  int i, answer;
  int t1, t2, t3;

  printf("Testing decimaltoBT and BTtodecimal.\n");
  for (i=0; i<100; i++) {
    t1 = (rand() % 1000) - 500;
    decimaltoBT(&lena, a, t1);
    BTtodecimal(&lena, a, &t3);
    if (t3 != t1) {
      printf("Error : %d has been converted to %d\n", t1, t3);
    };
  };
  printf("Testing add.\n");
  for (i=0; i<100; i++) {
    t1 = (rand() % 1000) - 500;
    t2 = (rand() % 1000) - 500;
    decimaltoBT(&lena, a, t1);
    decimaltoBT(&lenb, b, t2);
    add(&lena, &lenb, &lenc, a, b, c);
    BTtodecimal(&lenc, c, &t3);
    if (t3 != (t1+t2)) {
      printf("add gives %d + %d = %d\n", t1, t2, t3);
      printf("Error : answer should be %d\n", t1+t2);
    };
  };
  printf("Testing sub.\n");
  for (i=0; i<100; i++) {
    t1 = (rand() % 1000) - 500;
    t2 = (rand() % 1000) - 500;
    decimaltoBT(&lena, a, t1);
    decimaltoBT(&lenb, b, t2);
    sub(&lena, &lenb, &lenc, a, b, c);
    BTtodecimal(&lenc, c, &t3);
    if (t3 != (t1-t2)) {
      printf("add gives %d + %d = %d\n", t1, t2, t3);
      printf("Error : answer should be %d\n", t1-t2);
    };
  };
  printf("Testing mul.\n");
  for (i=0; i<100; i++) {
    t1 = (rand() % 10000) - 5000;
    t2 = (rand() % 10000) - 5000;
    decimaltoBT(&lena, a, t1);
    decimaltoBT(&lenb, b, t2);
    mul(&lena, &lenb, &lenc, a, b, c);
    BTtodecimal(&lenc, c, &t3);
    if (t3 != (t1*t2)) {
      printf("mul gives %d * %d = %d\n", t1, t2, t3);
      printf("Error : answer should be %d\n", t1*t2);
    };
  };
  printf("Testing div.\n");
  for (i=0; i<100; i++) {
    t1 = (rand() % 1000) - 500;
    t2 = (rand() % 50) - 25;
    if (t2 == 0) {
      t2 = 1;
    };
    decimaltoBT(&lena, a, t1);
    decimaltoBT(&lenb, b, t2);
    div(&lena, &lenb, &lenc, &lenrem, a, b, c, rem);
    BTtodecimal(&lenc, c, &t3);
    if (t3 != (t1/t2)) {
      printf("div gives %d / %d = %d\n", t1, t2, t3);
      printf("Error : answer should be %d\n", t1/t2);
    };
  };
};


Mac Buster
Retired
Posts: 1474
Joined: 03 Aug 2003 22:37
Location: Moscow

Re: Balanced ternary arithmetics

Post by Mac Buster »

Also on his site was a Java-based calculator to be used with balanced ternary numbers. Here is source code for it:

Code: Select all

import java.awt.*;
import java.util.*;
import java.applet.Applet;

///* Developed by James Allwright,                   */
///* Department of Electronics and Computer Science, */
///* University of Southampton, UK                   */

public class Calculator extends Applet {
  stackbox thestack = new stackbox();
  keypad keys = new keypad(thestack);

  public void init() {
    Label label;
    int j;

//    label = new Label("Balanced Ternary Calculator", Label.CENTER);
//    add(label);
    add(keys);
    add(thestack);
  }

  public boolean handleEvent(Event e) {
    int j;

    if ((e.target == thestack.decimalbox) && (e.id == Event.ACTION_EVENT)) {
      thestack.fromdecimal();
    }
    return false;
  }

}

class keypad extends Panel {

  Button PlusOne, Zero, MinusOne, AC;
  Button Push, Pop;
  Button Add, Sub, Mul, Div;
  Button Decimal;
  Button Neg;
  stackbox astack;

  public keypad(stackbox thestack) {

    setLayout(new GridLayout(3, 4));
    astack = thestack;
    MinusOne = new Button("-1");
    Zero = new Button("0");
    PlusOne = new Button("+1");
    AC = new Button("AC");
    add(MinusOne);
    add(Zero);
    add(PlusOne);
    add(AC);
    Add = new Button("+");
    Sub = new Button("-");
    Mul = new Button("x");
    Div = new Button("/");
    add(Add);
    add(Sub);
    add(Mul);
    add(Div);
    Push = new Button("PUSH");
    Pop = new Button("POP");
    add(Push);
    add(Pop);
    Decimal = new Button("DEC");
    add(Decimal);
    Neg = new Button("NEG");
    add(Neg);
  }

  public boolean handleEvent(Event e) {
    int j;

    if (e.target == MinusOne) {
      astack.setdigit(-1);
    }
    if (e.target == Zero) {
      astack.setdigit(0);
    }
    if (e.target == PlusOne) {
      astack.setdigit(1);
    }
    if (e.target == AC) {
      astack.clear();
    }
    if (e.target == Push) {
      astack.push();
    }
    if (e.target == Pop) {
      astack.pop();
    }
    if (e.target == Add) {
      astack.add();
    }
    if (e.target == Sub) {
      astack.sub();
    }
    if (e.target == Mul) {
      astack.mul();
    }
    if (e.target == Div) {
      astack.div();
    }
    if (e.target == Decimal) {
      astack.todecimal();
    }
    if (e.target == Neg) {
      astack.neg();
    }
    return false;
  }

}

class stackbox extends Panel {
  int place = 0;
  BTnumber result = new BTnumber();
  BTnumber stack[] = new BTnumber[5];
  TextField stacktext[] = new TextField[5];
  TextField decimalbox;
  BTnumber plus_one = new BTnumber();
  boolean onresult = false;
  boolean overflow;

  stackbox() {
    int j;

    setLayout(new GridLayout(6, 1));
    for (j=4; j>=0; j--) {
      stack[j] = new BTnumber();
      stacktext[j] = new TextField("", stack[j].MAXLEN);
      add(stacktext[j]);
    }
    decimalbox = new TextField("", 11);
    add(decimalbox);
    refresh(place);
    plus_one.AddDigit(1);
  }

  void refresh(int n) {
    stacktext[n].setText(stack[n].textify());
  }

  void setzero(int n) {
    stack[n].zero();
    refresh(n);
  }

  void clear() {
    if (onresult) {
      error("");
      onresult = false;
      if (place < 4) {
        place = place + 1;
      }
    }
    setzero(place);
  }

  void setnull(int n) {
    stack[n].zero();
    stacktext[n].setText("");
  }

  void setdigit(int d) {
    if (onresult) {
      error("");
      onresult = false;
      if (place < 4) {
        place = place + 1;
      }
      setzero(place);
    }
    stack[place].AddDigit(d);
    refresh(place);
  }

  void error(String text) {
    decimalbox.setText(text);
  }

  boolean pre_binary_op() {
    error("");
    overflow = false;
    if (place > 0) {
      return true;
    } else {
      return false;
    }
  }

  void post_binary_op() {
    setnull(place);
    place = place -1;
    onresult = true;
    refresh(place);
  }

  void pop() {
    error("");
    stack[place].zero();
    setnull(place);
    if (place > 0) {
      place = place - 1;
      onresult = true;
      refresh(place);
    } else {
      onresult = false;
    }
  }

  void push() {
    onresult = true;
  }

  BTnumber addnum(BTnumber a, BTnumber b) {
  /* c = a + b */
  /* add together 2 numbers in balanced ternary */
    int carry, i, digit;
    BTnumber c = new BTnumber();
  
    carry = 0;
    i = 0;
    c.digit[i] = 0;
    while ((carry != 0) || (i < a.length) || (i < b.length)) {
      c.digit[i] = carry;
      if (i < a.length) {
        c.digit[i] = c.digit[i] + a.digit[i];
      }
      if (i < b.length) {
        c.digit[i] = c.digit[i] + b.digit[i];
      }
      carry = 0;
      if (c.digit[i] > 1) {
        c.digit[i] = c.digit[i] - 3;
        carry = 1;
      }
      if (c.digit[i] < -1) {
        c.digit[i] = c.digit[i] + 3;
        carry = -1;
      }
      i = i + 1;
      if ((i == c.MAXLEN) && (carry != 0)) {
        carry = 0;
        overflow = true;
      }
    }
    if (overflow) {
      c.zero();
      error("Overflow Error");
    } else {
      c.length = i;
      while ((c.length > 0) && (c.digit[c.length-1] == 0)) {
        c.length = c.length - 1;
      }
    }
    return c;
  }

  BTnumber subnum(BTnumber a, BTnumber b) {
    BTnumber t = new BTnumber();

    t.takevalue(b);
    t.negate();
    return addnum(a, t);
  }

  BTnumber mulnum(BTnumber a, BTnumber b)
  /* multiply together 2 numbers in balanced ternary */
  {
    BTnumber c = new BTnumber();
    BTnumber d = new BTnumber();
    int i;
 
    if ((a.length + b.length - 2) > a.MAXLEN) {
      error("Overflow Error");
      return c;
    }
    d.takevalue(b);
    for (i=0; i < a.length; i++) {
      if (a.digit[i] == 1) {
        /* c = c + d */
        c = addnum(c, d);
      }
      if (a.digit[i] == -1) {
        /* c = c - d */
        c = subnum(c, d);
      }
      if (i != a.length-1) {
        mshift(d);
      }
    }
    if (overflow) {
      c.zero();
      error("Overflow Error");
    }
    return c;
  }

  int compare(BTnumber a, BTnumber b)
  /*  used by div         */
  /*  returns :           */
  /*    1  if  a >  b     */
  /*    0  if  a == b     */
  /*   -1  if  a <  b     */
  
  {
    int signa, signb;
    int place;
    
    if (a.length > b.length) {
      return(1);
    }
    if (a.length < b.length) {
      return(-1);
    }
    /* get sign of a and b */
    signa = a.digit[a.length-1];
    signb = b.digit[b.length-1];
    place = a.length - 1;
    while ((place >= 0) && (signa*a.digit[place] == signb*b.digit[place])) {
      place = place -1;
    }
    if (place == -1) {
      return(0);
    } else {
      if (signa*a.digit[place] > signb*b.digit[place]) {
        return(1);
      } else {
        return(-1);
      }
    }
  }
  
  BTnumber divnum(BTnumber a_in, BTnumber b_in)
  /*  divide numbers in balanced ternary  */
  /*  calculates a_in / b_in, returning   */
  /*  c = result, a = remainder           */
  /*  algorithm is like decimaltoBT       */
  /*  a and b are working copies of a_in and b_in */
  {
    BTnumber a = new BTnumber();
    BTnumber b = new BTnumber();
    BTnumber c = new BTnumber();
    BTnumber temp;
    int pos, digit;
 
    if (b_in.length == 0) {
      error("Division by zero");
      return c;
    } 
    if (a_in.length == a_in.MAXLEN) {
      error("Numerator too great");
      return c;
    }
    if (a_in.length == 0) {
      return c;
    }
    a.takevalue(a_in);
    b.takevalue(b_in);
    pos = 0;
    digit = - 1;
    /* align b appropriately */
    while (b.length < (a.length+1)) {
      mshift(b);
      pos = pos + 1;
    }
    while (b.length > (a.length+1)) {
      dshift(b);
      pos = pos - 1;
    }
    if (pos >= 0) {
      c.length = pos + 1; /* initial guess at length of result */
    }
  
    while ((a.length > 0) && (pos >= 0) && (b.length > 0)) {
      /* decide whether to try +b or -b */
      if (a.digit[a.length - 1] == b.digit[b.length - 1]) {
        digit = - digit;
        /* b = -b */
        b.negate();
      }
      /* temp = a + b */
      temp = addnum(a, b);
      if (compare(a, temp) == 1) {
        /* accept digit */
        /* a = temp */
        a = temp;
        c.digit[pos] = digit;
      } else {
        /* don't accept digit */
        c.digit[pos] = 0;
      }
      pos = pos - 1;
      dshift(b);
    }
    /* if we've reduced a to zero, fill in the remaining digits with 0 */
    while (pos >= 0) {
      c.digit[pos] = 0;
      pos = pos - 1;
    }
    /* correct the length of the result */
    while ((c.length > 0) && (c.digit[c.length-1] == 0)) {
      c.length = c.length - 1;
    }
    /* ensure that the remainder is the same sign as a_in */
    if (a.length > 0) { /* no problem if there is no remainder */
      if (a_in.digit[a_in.length - 1] != a.digit[a.length-1]) {
        if ((a_in.digit[a_in.length - 1] == b_in.digit[b_in.length-1]) ) {
          /* a = a + b_in */
          a = addnum(a, b_in);
          /* c = c - 1 */
          c = subnum(c, plus_one);
        } else {
          /* a = a - b_in */
          a = subnum(a, b_in);
          /* c = c + 1 */
          c = addnum(c, plus_one);
        }
      }
    }
    return c;
  }
  
  long BTtodecimal(BTnumber a)
  /* convert Balanced Ternary to decimal */
  {
    long result;
    long b;
    int i;
  
    b = 1;
    result = 0;
    for (i=0; i < (a.length); i++) {
      result = result + b * a.digit[i];
      b = b * 3;
    }
    return result;
  }
  
  BTnumber decimaltoBT(long value) {
  /* convert decimal to Balanced Ternary */
    BTnumber result = new BTnumber();
    long target, val, goal;
    int pos;
  
    result.length = 0;
    target = value;
    pos = 0;
    val = 1;
    goal  = 2 * target;
    if (goal < 0) {
      goal = -goal;
    }
    while (val < goal) {
      val = 3 * val;
      pos = pos + 1;
    }
    if (pos >= result.MAXLEN-1) {
      error("Overflow error");
      pos = -1;
    }
    if ( target < 0) {
      val = -val;
    }
    while (pos >= 0) {
      if (Math.abs(target-val) < Math.abs(target)) {
        if (val > 0) {
          result.digit[pos] = 1;
          target = target - val;
        } else {
          result.digit[pos] = -1;
          target = target - val;
        }
        if (result.length == 0) {
          result.length = pos+1;
        }
      } else {
        result.digit[pos] = 0;
      }
      val = val / 3;
      pos = pos - 1;
      /* make target and val the same sign */
      if ((target * val) < 0) {
        val = -val;
      }
    }
    return result;
  }
  
  void mshift(BTnumber n)
  /* shift left one place (multiply by 3) */
  {
    int i;
  
    if (n.length == n.MAXLEN) {
      error("Overflow Error");
    } else {
      n.length = n.length + 1;
      for (i=n.length-1; i>0; i--) {
        n.digit[i] = n.digit[i-1];
      }
      n.digit[0] = 0;
    }
  }
  
  void dshift(BTnumber n)
  /* shift right one place (divide by 3) */
  {
    int i;
  
    if (n.length > 0) {
      n.length = n.length - 1;
      for (i=0; i<n.length; i++) {
        n.digit[i] = n.digit[i+1];
      }
    }
  }
  

  void add() {
    if (pre_binary_op()) {
      stack[place-1] = addnum(stack[place], stack[place-1]);
      post_binary_op();
    }
  }

  void sub() {
    if (pre_binary_op()) {
      stack[place-1] = subnum(stack[place], stack[place-1]);
      post_binary_op();
    }
  }

  void mul() {
    if (pre_binary_op()) {
      stack[place-1] = mulnum(stack[place], stack[place-1]);
      post_binary_op();
    }
  }

  void div() {
    if (pre_binary_op()) {
      stack[place-1] = divnum(stack[place], stack[place-1]);
      post_binary_op();
    }
  }

  void todecimal() {
    long t;

    t = BTtodecimal(stack[place]);
    decimalbox.setText(String.valueOf(t));
  }

  void fromdecimal() {
    long t;

    if (onresult) {
      onresult = false;
      if (place < 4) {
        place = place + 1;
      }
    }
    t = Integer.valueOf(decimalbox.getText()).longValue();
    stack[place] = decimaltoBT(t);
    decimalbox.setText("");
    refresh(place);
    onresult = true;
  }

  void neg() {
    stack[place].negate();
    refresh(place);
  }
}

class BTnumber {
  static int MAXLEN = 20;
  int digit[] = new int[MAXLEN];
  int length;

  BTnumber() {
    this.length = 0;
  }

  public void takevalue(BTnumber n) {
    int j;

    this.length = n.length;
    for (j=0; j<length; j++) {
      this.digit[j] = n.digit[j];
    }
  }

  public void AddDigit(int d) {
    int j;

    if ((length > 0) || (d != 0)) {
      if (length < MAXLEN) {
        for (j=this.length; j>0; j--) {
          this.digit[j] = this.digit[j-1];
        }
        this.digit[0] = d;
        this.length = this.length + 1;
      }
    }
  }

  public void zero() {
    this.length = 0;
  }

  public String textify() {
    int j;
    StringBuffer out;
    String map = "-01";
    out = new StringBuffer(MAXLEN);

    if (this.length <= 0) {
      out.append("0");
    } else {
      for (j=this.length-1; j>=0; j--) {
        out.append(map.charAt(this.digit[j]+1));
      }
    }
    return out.toString();
  }

  void negate() {
  /* a = -a */
    int i;
  
    for (i=0; i < length; i++) {
      digit[i] = -digit[i];
    }
  }

}

Mac Buster
Retired
Posts: 1474
Joined: 03 Aug 2003 22:37
Location: Moscow

Re: Balanced ternary arithmetics

Post by Mac Buster »

And the html-source to run calculator applet:

Code: Select all

<HTML>
<HEAD>
<BASE HREF="http://perun.hscs.wmin.ac.uk/~jra/ternary/calculator/">

<TITLE>Balanced Ternary Calculator</TITLE>
</HEAD>
<BODY bgcolor="#FFFFFF">
<h1>Balanced Ternary Calculator</h1>
Below is a simple stack-based balanced ternary calculator written in Java.
<APPLET CODE="Calculator.class" WIDTH=400 HEIGHT=200>
</APPLET>
<P>
The buttons are :
<UL>
<LI><b>-1</b>, <b>0</b> and <b>+1</b> to enter a number.

<LI><b>AC</b> clear entry and start again.
<LI><b>PUSH</b> entry finished - ready to enter next number.
<LI><b>POP</b> remove top item from stack.
<LI><b>+</b>, <b>-</b>, <b>x</b> and <b>/</b> perform the appropriate action 
on the top 2 items on the stack. 

<LI><b>DEC</b> display decimal value of current number in the bottom slot. 
<LI><b>NEG</b> negate current entry.
</UL>
Enter a decimal number in the
bottom slot and it will be converted to balanced ternary and placed on the
stack.
<p>
Here is the <A HREF="Calculator.java">Java source</A>.
<HR>
Written by <A HREF="http://diana.ecs.soton.ac.uk/~jra/cv.html">James 
Allwright</A>.
</BODY>

<SCRIPT language="Javascript">
<!--

// FILE ARCHIVED ON 20040906154742 AND RETRIEVED FROM THE
// INTERNET ARCHIVE ON 20080813074243.
// JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
// ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
// SECTION 108(a)(3)).

   var sWayBackCGI = "http://web.archive.org/web/20040906154742/";

   function xResolveUrl(url) {
      var image = new Image();
      image.src = url;
      return image.src;
   }
   function xLateUrl(aCollection, sProp) {
      var i = 0;
      for(i = 0; i < aCollection.length; i++) {
         if (typeof(aCollection[i][sProp]) == "string") { 
          if (aCollection[i][sProp].indexOf("mailto:") == -1 &&
             aCollection[i][sProp].indexOf("javascript:") == -1) {
            if(aCollection[i][sProp].indexOf("http") == 0) {
                aCollection[i][sProp] = sWayBackCGI + aCollection[i][sProp];
            } else {
                aCollection[i][sProp] = sWayBackCGI + xResolveUrl(aCollection[i][sProp]);
            }
         }
         }
      }
   }

   xLateUrl(document.getElementsByTagName("IMG"),"src");
   xLateUrl(document.getElementsByTagName("A"),"href");
   xLateUrl(document.getElementsByTagName("AREA"),"href");
   xLateUrl(document.getElementsByTagName("OBJECT"),"codebase");
   xLateUrl(document.getElementsByTagName("OBJECT"),"data");
   xLateUrl(document.getElementsByTagName("APPLET"),"codebase");
   xLateUrl(document.getElementsByTagName("APPLET"),"archive");
   xLateUrl(document.getElementsByTagName("EMBED"),"src");
   xLateUrl(document.getElementsByTagName("BODY"),"background");
   var forms = document.getElementsByTagName("FORM");
   if (forms) {
       var j = 0;
       for (j = 0; j < forms.length; j++) {
              f = forms[j];
              if (typeof(f.action)  == "string") {
                 if(typeof(f.method)  == "string") {
                     if(typeof(f.method) != "post") {
                        f.action = sWayBackCGI + f.action;
                     }
                  }
              }
        }
    }


//-->
</SCRIPT>

</HTML>


hemuman

Re: Balanced ternary arithmetics

Post by hemuman »

Thanks, for the code,
actually i was looking for the code for devision, and its there....:-)
Mac Buster
Retired
Posts: 1474
Joined: 03 Aug 2003 22:37
Location: Moscow

Re: Balanced ternary arithmetics

Post by Mac Buster »

Yes, it seems to be the only public code that does division with balanced ternary numbers.
eudoxie
Maniac
Posts: 277
Joined: 17 Sep 2012 13:36
Location: 81.170.128.52

Re: Balanced ternary arithmetics

Post by eudoxie »

Do you know what license it's released under?
Mac Buster
Retired
Posts: 1474
Joined: 03 Aug 2003 22:37
Location: Moscow

Re: Balanced ternary arithmetics

Post by Mac Buster »

I've got no idea about license, he just uploaded the code to his own web-site, nothing more.
User avatar
Shaos
Admin
Posts: 23989
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Balanced ternary arithmetics

Post by Shaos »

eudoxie wrote: Do you know what license it's released under?
There is no copyright notice, just "Developed by James Allwright" message, so it looks like "public domain"...

See some historical snapshot of that web-page from 2005:

http://web.archive.org/web/200502110914 ... a/ternary/

E-mail of author is J.R.Allwright@westminster.ac.uk
User avatar
Shaos
Admin
Posts: 23989
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

up
Я тут за главного - если что шлите мыло на me собака shaos точка net