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

package main

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

type Opts struct {
  From string
  To string
  Numbers []string
}

func ParseOpts() Opts {
  var opts Opts

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

  opts.Numbers = flag.Args()

  return opts
}

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 := ParseOpts()

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

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