89 lines
1.9 KiB
Go
89 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"math/big"
|
|
)
|
|
|
|
// DC for dollars and cents. Value is an integer number of cents.
|
|
type DC int64
|
|
|
|
func (dc DC) String() string {
|
|
d := dc / 100
|
|
if dc < 0 {
|
|
dc = -dc
|
|
}
|
|
return fmt.Sprintf("%d.%02d", d, dc%100)
|
|
}
|
|
|
|
// Extend returns extended price of a unit price.
|
|
func (dc DC) Extend(n int) DC {
|
|
return dc * DC(n)
|
|
}
|
|
|
|
var one = big.NewInt(1)
|
|
var hundred = big.NewRat(100, 1)
|
|
|
|
// ParseDC parses dollars and cents as a string into a DC.
|
|
func ParseDC(s string) (DC, bool) {
|
|
r, ok := new(big.Rat).SetString(s)
|
|
if !ok {
|
|
return 0, false
|
|
}
|
|
r.Mul(r, hundred)
|
|
if r.Denom().Cmp(one) != 0 {
|
|
return 0, false
|
|
}
|
|
return DC(r.Num().Int64()), true
|
|
}
|
|
|
|
// TR for tax rate. Value is an an exact rational.
|
|
type TR struct {
|
|
*big.Rat
|
|
}
|
|
func NewTR() TR {
|
|
return TR{new(big.Rat)}
|
|
}
|
|
|
|
// SetString overrides Rat.SetString to return the TR type.
|
|
func (tr TR) SetString(s string) (TR, bool) {
|
|
if _, ok := tr.Rat.SetString(s); !ok {
|
|
return TR{}, false
|
|
}
|
|
return tr, true
|
|
}
|
|
|
|
var half = big.NewRat(1, 2)
|
|
|
|
// Tax computes a tax amount, rounding to the nearest cent.
|
|
func (tr TR) Tax(dc DC) DC {
|
|
r := big.NewRat(int64(dc), 1)
|
|
r.Add(r.Mul(r, tr.Rat), half)
|
|
return DC(new(big.Int).Div(r.Num(), r.Denom()).Int64())
|
|
}
|
|
|
|
func main() {
|
|
hamburgerPrice, ok := ParseDC("5.50")
|
|
if !ok {
|
|
log.Fatal("Invalid hamburger price")
|
|
}
|
|
milkshakePrice, ok := ParseDC("2.86")
|
|
if !ok {
|
|
log.Fatal("Invalid milkshake price")
|
|
}
|
|
taxRate, ok := NewTR().SetString("0.0765")
|
|
if !ok {
|
|
log.Fatal("Invalid tax rate")
|
|
}
|
|
|
|
totalBeforeTax := hamburgerPrice.Extend(4000000000000000) +
|
|
milkshakePrice.Extend(2)
|
|
tax := taxRate.Tax(totalBeforeTax)
|
|
total := totalBeforeTax + tax
|
|
|
|
fmt.Printf("Total before tax: %22s\n", totalBeforeTax)
|
|
fmt.Printf(" Tax: %22s\n", tax)
|
|
fmt.Printf(" Total: %22s\n", total)
|
|
}
|