swiftternary

How do I convert a floating point number into balanced ternary?


Here I have some code that converts balanced ternary (-, 0, +) as a string of minuses, zeroes, and pluses into a floating point number (a double). How do I invert this function? I want to get the balanced ternary equivalent of a floating point number.

public static func convertBT2FL(ternaryString: String) -> Double {
        
        var exp : Double = 0
        var sum : Double = 0
        
        for trit in ternaryString {
            var tritN : Double = 0
            if trit == "+" {
                tritN = 1
            } else if trit == "0" {
                tritN = 0
            } else if trit == "-" {
                tritN = -1
            }
            sum += tritN * pow(3.0, exp)
            exp -= 1
        }
        
        return sum
    }
public static func convertFL2BT(doubleValue: Double) -> String {

//invert function here

}

I know how to normalize the number so that it's always between -1.5 and 1.5 (so the significand is always representable as something like +.-++-++ and not +-++.-++) by doing the following:

var n = ceil((log(abs(significandValueDouble)) - log(1.5)) / log(3))
        
var newSignificand = significandValueDouble / pow(3.0, n)

But I'm at a loss for how to convert the resulting newSignificand into balanced ternary. I found a site that does this sort of conversion https://chridd.nfshost.com/convert/original but I haven't been able to figure out how to do it myself.


Solution

  • For 19 digits of balanced ternary, the answer is (messy):

    for n in Range(uncheckedBounds: (0, 19)) {
                if ( abs( sum - -1 * pow(3.0, Double(-n)) ) < abs( sum - 1 * pow(3.0, Double(-n)) ) ) && ( abs( sum - -1 * pow(3.0, Double(-n)) ) < abs(sum) ){
                    sum -= -1 * pow(3.0, Double(-n))
                    significand += "-"
                } else if ( abs( sum - -1 * pow(3.0, Double(-n)) ) > abs( sum - 1 * pow(3.0, Double(-n))) ) && ( abs( sum - 1 * pow(3.0, Double(-n))) < abs(sum) ) {
                    sum -= 1 * pow(3.0, Double(-n))
                    significand += "+"
                } else {
                    significand += "0"
                }
            }
    

    This takes the absolute value of the difference between the sum and two options - it tries it with either a 1 or a -1 multiplied by 3 to the power of n as n goes from the first digit to the last (left to right), and whichever is smallest wins, and gets added to the string significant as a + or a - (including if the 1 or -1 are equal or both greater than the sum, in which case it's a zero)