Source File: go-coreutils/numfmt/main.go

package main

import (
    "fmt"
    "flag"
    "strconv"
    "log"
    "math"
    "bufio"
    "os"
)

type Opts struct {
    From string
    To string
}

func parse_opts() (Opts, []string) {
    var opts Opts

    flag.StringVar(&opts.From, "from", "", "Convert from")
    flag.StringVar(&opts.To, "to", "", "Convert to")
    flag.Parse()

    return opts, flag.Args()
}

func to_si(num string) string {
    number, err := strconv.ParseFloat(num, 64)
    if err != nil { log.Fatal("that's not a number") }
    mag := math.Floor(math.Log10(number))

    switch {
    case mag < 3:
        return num
    case mag == 3:
        // need to separate k from hundres
        as_k := math.Floor(float64(number) / 1000.0)
        mod := math.Ceil(float64(int(number) % 1000))
        return fmt.Sprintf("%d.%dk", int(as_k), int(mod))
    case mag > 3 && mag < 6: 
        as_m := math.Ceil(float64(number) / 1000.0)
        return fmt.Sprintf("%dk", int(as_m))
    case mag == 6:
        // need to separate mil from k
        as_m := math.Floor(float64(number) / 1000000.0)
        mod := math.Ceil(float64(int(number) % 1000000) / 1000.0)
        return fmt.Sprintf("%d.%dM", int(as_m), int(mod))
    case mag > 6 && mag <= 9:
        as_m := math.Ceil(float64(number) / 1000000.0)
        return fmt.Sprintf("%dM", int(as_m))
    default:
        return fmt.Sprintf("%sbesos", num)
    }
}

func main() {
    opts, nums := parse_opts()

    if opts.From != "" {
        log.Fatal("you should implement this")
    }

    if len(nums) == 0 {
        scanner := bufio.NewScanner(os.Stdin)
        for scanner.Scan() {
            num := scanner.Text()
            fmt.Println(to_si(num))
        }
    } else {
        for _, num := range nums {
            fmt.Println(to_si(num))
        }
    }
}