Skip to content

Instantly share code, notes, and snippets.

@rjeczalik
Created December 8, 2014 12:55
Show Gist options
  • Save rjeczalik/4ab0c4bae1be760e94ac to your computer and use it in GitHub Desktop.
Save rjeczalik/4ab0c4bae1be760e94ac to your computer and use it in GitHub Desktop.
package main
import (
"errors"
"fmt"
"log"
"reflect"
"strconv"
"strings"
)
type Percentage uint
func (p *Percentage) Set(s string) error {
if strings.HasSuffix(s, "%") {
s = s[:len(s)-1]
}
if strings.Contains(s, ".") {
j, k := 0, ""
n, err := fmt.Sscanf(s, "%d.%4s", &j, &k)
if err != nil {
return err
}
if n == 0 {
errors.New("invalid value: " + s)
}
*p = Percentage(j * 1000)
if n == 2 && k != "" {
fmt.Println("k =", k)
if n, err = strconv.Atoi(k); err != nil {
return err
}
switch len(k) {
case 2:
n *= 10
case 1:
n *= 100
}
switch {
case n > 9994:
*p += 1000
case n > 994:
*p += Percentage((n + 5) / 10)
default:
*p += Percentage(n)
}
fmt.Println("n =", n)
}
return nil
}
n, err := fmt.Sscanf(s, "%d", p)
if err != nil {
return err
}
if n == 0 {
errors.New("invalid value: " + s)
}
*p *= 1000
return nil
}
func (p Percentage) String() string {
return fmt.Sprintf("%d.%d%%", p/1000, p%1000)
}
func (p Percentage) Apply(number interface{}) {
switch v := reflect.ValueOf(number).Elem(); v.Kind() {
case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v.SetInt((v.Int() * int64(p)) / 100000)
case reflect.Float32, reflect.Float64:
v.SetFloat((v.Float() * float64(p)) / 100000)
default:
panic("argument to Apply must be number")
}
}
func main() {
var p Percentage
i := 1000
if err := p.Set("0.9995%"); err != nil {
log.Fatal(err)
}
p.Apply(&i)
fmt.Println(int(p), i)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment