Decimal-to-fraction solver I have created a program that turns a decimal into a fraction:

package main

import (
        "fmt"
        "github.com/retep-mathwizard/utils/convert"
        "github.com/retep-mathwizard/utils/input"
        "math"
        "strings"
)

func main() {
        fmt.Println("Input your decimal")
        num := input.StringInput(" &gt; ")
        digits := num[strings.Index(num, ".")+1:]
        decimal := num[strings.Index(num, "."):]
        numbers := num[:strings.Index(num, ".")]
        denom := convert.FloatToInt(math.Pow(10, convert.IntToFloat(len(digits))))
        numer := convert.FloatToInt(convert.StringToFloat(decimal) * convert.IntToFloat(denom))
        var gcf int
        for i := numer/2 + 1; i &gt;= 0; i-- {
                if (numer%i == 0) &amp;&amp; (denom%i == 0) {
                        gcf = i
                        break
                }

        }
        newnum := numer / gcf
        newdum := denom / gcf
        fmt.Println(numbers+" and ", newnum)
        fmt.Println("    -------")
        fmt.Println("      ", newdum)
}


I need to implement repeating fractions, and a maximum decimal length. Over 13 digits, and it takes a while. Feel free to butcher my code!
Note: Your code is not useful. Rational numbers are available in the Go math/big standard library. For example,

package main

import (
    "fmt"
    "math/big"
)

func main() {
    fmt.Println("Enter a number:")
    var r = new(big.Rat)
    fmt.Scanln(r)
    fmt.Println(r)
}




I read your code, the code you imported from github.com/retep-mathwizard, and the code from rolfl's answer. I see problems.

Let's start with something simple, the calculation of the greatest common divisor or factor.

You embedded this code in a slab of code. It should be a function. For example,

func gcf(numer, denom int) int {
    var gcf int
    for i := numer/2 + 1; i &gt;= 0; i-- {
        if (numer%i == 0) &amp;&amp; (denom%i == 0) {
            gcf = i
            break
        }
    }
    return gcf
}


It's very inefficient. For well over two thousand years we have known of a much better way to do this.

Rolfl used a much better algorithm.

// Euclidian algorithm
func gcf(a, b int64) int64 {

    if a &lt; b {
        return gcf(b, a)
    }

    if b == 0 {
        return a
    }

    a = a % b
    return gcf(b, a)
}


If you put blank lines between each sentence you can't see very much on a single screen. It's essential that code be readable. Think of blank lines as more like paragraph separators.

The algorithm is implemented using recursion. Any recursive algorithm can be written as an iterative algorithm. Go doesn't have tail recursion. Limit the use of recursion to the few cases where recursion is much easier to understand than iteration.

Here's an idiomatic Go GCD function. It's simple, direct, and fast.

func gcd(x, y int64) int64 {
    for y != 0 {
        x, y = y, x%y
    }
    return x
}


Here are some Go benchmarks which show how slow your GCF algorithm is.

BenchmarkGCFXXX        30000         54564 ns/op    
BenchmarkGCFPeter   10000000           156 ns/op


Go types play an essential role in writing idiomatic Go. Rational is an obvious type:

// A rational number r is expressed as the fraction p/q of two integers:
// r = p/q = (d*i+n)/d.
type Rational struct {
    i int64 // integer
    n int64 // fraction numerator
    d int64 // fraction denominator
}


Like many types, Rational should have a formatted string function. Your formatted output is ugly

7182818284590 and  141592653
    -------
       1000000000


I think this looks much better

7182818284590 + 141592653/1000000000


Here's a Go String method for the Rational type. Note the attention to pretty-printing details.

func (r Rational) String() string {
    var s string
    if r.i != 0 {
        s += strconv.FormatInt(r.i, 10)
    }
    if r.n != 0 {
        if r.i != 0 {
            s += " + "
        }
        if r.d &lt; 0 {
            r.n *= -1
            r.d *= -1
        }
        s += strconv.FormatInt(r.n, 10) + "/" + strconv.FormatInt(r.d, 10)
    }
    if len(s) == 0 {
        s += "0"
    }
    return s
}


An obvious indication of problems is the difficulty in testing. Your program only handles one input value. Rolfl hardcoded a single fixed value: num := "12345.6785".

For a problem like this, which is driven by user input, the Go main function should be an input loop. For example,

func main() {
    snr := bufio.NewScanner(os.Stdin)
    enter := "Enter a decimal number:"
    for fmt.Println(enter); snr.Scan(); fmt.Println(enter) {
        d := snr.Text()
        if len(d) == 0 {
            break
        }
        r, err := ParseDecimal(d)
        if err != nil {
            fmt.Fprintln(os.Stderr, "Input error:", err)
            continue
        }
        fmt.Println(r)
    }
    if err := snr.Err(); err != nil {
        if err != io.EOF {
            fmt.Fprintln(os.Stderr, err)
        }
    }
}


Now we have an easy way to test. Let's make sure that we can handle all reasonable values. Here are some values that you don't handle.

0; 0.; -0; 1; -1; -1.1; 1.; and so on.

You should always expect the worst from user input and handle errors gracefully. For example,'

func ParseDecimal(s string) (r Rational, err error) {
    sign := int64(1)
    if strings.HasPrefix(s, "-") {
        sign = -1
    }
    p := strings.IndexByte(s, '.')
    if p &lt; 0 {
        p = len(s)
    }
    if i := s[:p]; len(i) &gt; 0 {
        if i != "+" &amp;&amp; i != "-" {
            r.i, err = strconv.ParseInt(i, 10, 64)
            if err != nil {
                return Rational{}, err
            }
        }
    }
    if p &gt;= len(s) {
        p = len(s) - 1
    }
    if f := s[p+1:]; len(f) &gt; 0 {
        n, err := strconv.ParseUint(f, 10, 64)
        if err != nil {
            return Rational{}, err
        }
        d := math.Pow10(len(f))
        if math.Log2(d) &gt; 63 {
            err = fmt.Errorf(
                "ParseDecimal: parsing %q: value out of range", f,
            )
            return Rational{}, err
        }
        r.n = int64(n)
        r.d = int64(d)
        if g := gcd(r.n, r.d); g != 0 {
            r.n /= g
            r.d /= g
        }
        r.n *= sign
    }
    return r, nil
}


Even if you write impeccable code, you will still be judged on the quality of the external packages that you use. The packages from github.com/retep-mathwizard/ are of very low quality.

Here's my complete program. It's a first draft.

package main

import (
    "bufio"
    "fmt"
    "io"
    "math"
    "os"
    "strconv"
    "strings"
)

// A rational number r is expressed as the fraction p/q of two integers:
// r = p/q = (d*i+n)/d.
type Rational struct {
    i int64 // integer
    n int64 // fraction numerator
    d int64 // fraction denominator
}

func (r Rational) String() string {
    var s string
    if r.i != 0 {
        s += strconv.FormatInt(r.i, 10)
    }
    if r.n != 0 {
        if r.i != 0 {
            s += " + "
        }
        if r.d &lt; 0 {
            r.n *= -1
            r.d *= -1
        }
        s += strconv.FormatInt(r.n, 10) + "/" + strconv.FormatInt(r.d, 10)
    }
    if len(s) == 0 {
        s += "0"
    }
    return s
}

func gcd(x, y int64) int64 {
    for y != 0 {
        x, y = y, x%y
    }
    return x
}

func ParseDecimal(s string) (r Rational, err error) {
    sign := int64(1)
    if strings.HasPrefix(s, "-") {
        sign = -1
    }
    p := strings.IndexByte(s, '.')
    if p &lt; 0 {
        p = len(s)
    }
    if i := s[:p]; len(i) &gt; 0 {
        if i != "+" &amp;&amp; i != "-" {
            r.i, err = strconv.ParseInt(i, 10, 64)
            if err != nil {
                return Rational{}, err
            }
        }
    }
    if p &gt;= len(s) {
        p = len(s) - 1
    }
    if f := s[p+1:]; len(f) &gt; 0 {
        n, err := strconv.ParseUint(f, 10, 64)
        if err != nil {
            return Rational{}, err
        }
        d := math.Pow10(len(f))
        if math.Log2(d) &gt; 63 {
            err = fmt.Errorf(
                "ParseDecimal: parsing %q: value out of range", f,
            )
            return Rational{}, err
        }
        r.n = int64(n)
        r.d = int64(d)
        if g := gcd(r.n, r.d); g != 0 {
            r.n /= g
            r.d /= g
        }
        r.n *= sign
    }
    return r, nil
}

func main() {
    snr := bufio.NewScanner(os.Stdin)
    enter := "Enter a decimal number:"
    for fmt.Println(enter); snr.Scan(); fmt.Println(enter) {
        d := snr.Text()
        if len(d) == 0 {
            break
        }
        r, err := ParseDecimal(d)
        if err != nil {
            fmt.Fprintln(os.Stderr, "Input error:", err)
            continue
        }
        fmt.Println(r)
    }
    if err := snr.Err(); err != nil {
        if err != io.EOF {
            fmt.Fprintln(os.Stderr, err)
        }
    }
}